轉載: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();
……
}