Android中LocalSocket使用


一 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

    http://blog.csdn.net/jamin0107/article/details/6832159


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM