Android LocalSocket

轉載:http://www.cnblogs.com/bastard/archive/2012/10/09/2717052.html

二 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();
  
  …… }
複製代碼


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章