一 Socket
Socket最初用在基於TCP/IP網絡間進程通信中,以客戶端/服務器模式進行通信。
實現異步操作,共享資源集中處理,提高客戶端響應能力。
Tcp通信基本流程:
服務器端 客戶端
1.創建socket 1.創建socket
2.bind()
3.listen()
4.accecp()
----等待客戶端連接---- 2.connect()
5.讀數據(recv) 3.寫數據(send)
6.寫數據(send) 4.讀數據(recv)
7.關閉socket(closesocket()) 5.關閉socket(closesocket())
數據流:

二 Android LocalSocket
LocalSocket
在Unix域名空間創建一個套接字(非服務端)。
是對Linux中Socket進行了封裝,采用JNI方式調用,實現進程間通信。
具體就是Native層Server和Framework層Client之間進行通信,或在各層次中能使用Client/Server模式實現通信。
LocalServerSocket
創建服務器端Unix域套接字,與LocalSocket對應。
LocalSocketImpl
Framework層Socket的實現,通過JNI調用系統socket API。
LocalSocketAddress
Unix域socket的地址以及所處的空間。
JNI訪問接口:\frameworks\base\core\jni\android_net_LocalSocketImpl.cpp
socket_create
socket_connect_local
socket_bind_local
socket_listen
……
下面看看這幾個類之間的關系:

使用Android的LocalSocket建立socket通信,是基於網絡socket過程一致的。
三 native與framework之間的通信
以install這個服務為例:
1 增加socket資源
\system\core\rootdir\init.rc中:
service installd /system/bin/installd
class main
socket installd stream 600 system system
在啟動install服務時,就會為install分配socket文件系統資源:dev/socket/installd
Install服務的Socket資源和名稱installd綁定起來。
這些都是在開機初始化化init進程中啟動service時完成:
service_start
create_socket
publish_socket
2 native層
install進程 建立服務端程序
native 層中作為server:\frameworks\base\cmds\installd\installd.c
int main(const int argc, const char *argv[]) { //獲取已綁定socket
lsocket = android_get_control_socket(SOCKET_PATH); //監聽socket
listen(lsocket, 5); for (;;) { //等待客戶端建立連接
s = accept(lsocket, &addr, &alen); for (;;) { //接收數據 相當於recv
readx(s, buf, count); //執行相關的操作
execute(s, buf); } //關閉socket
close(s); } }
3 framework層
客戶端程序:
\frameworks\base\services\java\com\android\server\pm\Installer.java
boolean connect() { //創建socket
mSocket = new LocalSocket(); //設置連接地址
LocalSocketAddress address = new LocalSocketAddress("installd", LocalSocketAddress.Namespace.RESERVED); //建立連接
mSocket.connect(address); //獲取數據輸入流 可以讀數據
mIn = mSocket.getInputStream(); //獲取數據輸出流 可以寫數據
mOut = mSocket.getOutputStream(); }
因此以native層service與framework建立client/server模式socket通信主要代碼:
java層主要代碼:
LocalSocket s =null; LocalSocketAddress l; s = new LocalSocket(); l = new LocalSocketAddress(SOCKET_NAME, LocalSocketAddress.Namespace.RESERVED); s.connect(l);
native層主要代碼:
s_fdListen = android_get_control_socket(SOCKET_NAME); ret = listen(s_fdListen, n); s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen);
init.rc中加入:
service myserver /system/bin/myserver class main socket myserver stream 600 system system ……
當然建立這種client/server模式並不一定要在native層和framework層,僅在framework層也能夠進行。
系統提供了LocalSocket作為客戶端使用,同時提供了LocalServerSocket作為服務端使用。
Zygote服務使用了LocalServerSocket作為服務端socket通信。
建立socket通信,也可以在代碼執行過程中進行,使用LocalSocket與LocalServerSocket。
在init.rc中為服務端建立的socket資源和初始化時綁定,與在代碼中使用LocalServerSocket
建立的服務端socket資源在Linux域空間不同而已,過程是一樣的跟一般的socket通信過程一致。
四 LocalSocket與LocalServerSocket建立socket通信
LocalSocket就是作為客戶端建立於服務端的連接,發送數據。
LocalServerSocket作為服務端使用,建立socket監聽客戶端請求。通過構造函數看到有兩種方式:
在Linux抽象空間 創建一個新的服務端socket:
public LocalServerSocket(String name) throws IOException { //創建socket資源
impl = new LocalSocketImpl(); impl.create(true); //綁定地址
localAddress = new LocalSocketAddress(name); impl.bind(localAddress); //監聽
impl.listen(LISTEN_BACKLOG); }
用文件描述符創建已經存在並且綁定的服務端socket:
如在init.rc中指定socket資源 dev/socket/……,zygote使用此方式創建作為服務端的socket
LocalServerSocket socket = new LocalServerSocket(createFileDescriptor(fileDesc));
public LocalServerSocket(FileDescriptor fd) throws IOException { //已綁定 監聽
impl = new LocalSocketImpl(fd); impl.listen(LISTEN_BACKLOG); localAddress = impl.getSockAddress(); }
通常使用過程中:
客戶端代碼:
String message; //創建socket
LocalSocket sender = new LocalSocket(); //建立對應地址連接
sender.connect(new LocalSocketAddress(SOCKET_ADDRESS)); //發送寫入數據
sender.getOutputStream().write(message.getBytes()); //關閉socket
sender.getOutputStream().close();
服務端:
//創建socket並綁定監聽 新創建的
LocalServerSocket server = new LocalServerSocket(SOCKET_ADDRESS); while (true) { //等待建立連接
LocalSocket receiver = server.accept(); //接收獲取數據流
InputStream input = receiver.getInputStream();
…… }
參考文檔:
http://hi.baidu.com/leoispace/item/ab4a271e6624824b6926bbe9
http://www.cnblogs.com/over140/archive/2011/11/22/2258372.html
