Android 进程间通信之LocalSocket
我们知道在Android上和网络的服务器通信手段有很多种, 通常我们的业务数据承载应用层协议(http等)或传输层协议上(tcp/udp)进行交互。 那么在传输层的Android上的技术接口无非就是socket,socket就是一套接口,可以使用网络,文件或内存来做为媒介进行通信,但是在android中都可以使用namespace来选择使用哪种方式进行通信。
我们都知道,其实在Linux中‘一切皆是文件’,包括socket。ipc socket进行通信的媒介有以下三种:
1.网络端口;
通过本地环回的虚接口(loopback),使用127.0.0.1作为回环地址,来收发数据。
2.文件系统;
通过文件来做为收发数据的中转,数据交换的媒介。
3. 内存映射;
通过在内存中开辟一块空间来做为收发数据的中转,也是通过文件的API接口完成的。
以上三种方式都可以作为在android中的ipc socket进行通信,在android中的localsocket 支持以上的#2和#3,从执行效率上来看,#3的效率要更高。
在android中使用LocalSocket的事例就是应用程序APP进程的创建过程。
当我们使用Context#startActivity启动一个Activity时,是需要先创建APP进程,而APP进程的创建是通过android zygote进程来创建的,那么AMS进程需要和zygote进程进行通信,
通信的媒介就是基于LocalSocketAddress$Namespace#RESERVED(也就是会在/dev/socket目录下创建一个socket文件)。
与zygote进程建立连接的关键方法:Process#openZygoteSocketIfNeeded
private static final String ZYGOTE_SOCKET = "zygote";private static void openZygoteSocketIfNeeded() throws ZygoteStartFailedEx { ... try { sZygoteSocket = new LocalSocket(); sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET, // LocalSocketAddress.Namespace.RESERVED)); ... break; } catch (IOException ex) { ... } }
LocalSocket可以直接通过new关键字进行创建,调用LocalSocket#connect,需要传递LocalSSocketAddress对象,这个对象需要传递一个名称,这个名称和服务端约定好。 第二参数既是Namespace,是一个enum类型的。连接成功之后,就可以向使用普通的socket对象一样,获取inputstream和outputstream和服务器进行通信,交互数据。
public class LocalSocketAddress{ public enum Namespace { /** A socket in the Linux abstract namespace */ ABSTRACT(0), /** * A socket in the Android reserved namespace in /dev/socket. * Only the init process may create a socket here. */ RESERVED(1), /** * A socket named with a normal filesystem path. */ FILESYSTEM(2); }}
zygote对应的服务端代码如下:
private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";/** * Registers a server socket for zygote command connections * * @throws RuntimeException when open fails */ private static void registerZygoteSocket() { if (sServerSocket == null) { int fileDesc; try { String env = System.getenv(ANDROID_SOCKET_ENV); fileDesc = Integer.parseInt(env); } catch (RuntimeException ex) { throw new RuntimeException( ANDROID_SOCKET_ENV + " unset or invalid", ex); } try { sServerSocket = new LocalServerSocket( createFileDescriptor(fileDesc)); } catch (IOException ex) { throw new RuntimeException( "Error binding to local socket '" + fileDesc + "'", ex); } } }static native FileDescriptor createFileDescriptor(int fd) throws IOException;
更多相关文章
- Android进程保活
- Android——进程通信/ AIDL/Message相关知识总结贴
- Android进程内存上限
- Android 实现蓝牙客户端与服务器端通信
- 浅谈Android中的线程的通信及Handle机制
- android蓝牙通信
- 理解Android进程创建流程(转)
- 从linux看Android之一--init进程