查看Android源码会发现很多地方如Zygote就用到了LocalServerSocket来监听请求,它可以用用于本地进程、线程通信,也可以用于网络通信,LocalSocket底层实质用到了C++的Socket套接字,对其做了一定的封装;在此,理解其背后的运作原理,可以帮助我们在分析源码时,快速了解一些源码机制问题
//创建socket并绑定监听 新创建的
LocalServerSocket server = new LocalServerSocket(SOCKET_NAME);
while (true) {
//等待建立连接
LocalSocket receiver = server.accept();
InputStream input = receiver.getInputStream();
}
LocalSocket client =null;
LocalSocketAddress add;
client = new LocalSocket();
服务端名字和端口
add = new LocalSocketAddress(SOCKET_NAME,LocalSocketAddress.Namespace.RESERVED);
client.connect(add);
从服务端分析入手,创建一个LocalServerSocket,如下源码:
public LocalServerSocket(String name) throws IOException
{
impl = new LocalSocketImpl();
配置socket套接字的协议、传输格式等
impl.create(LocalSocket.SOCKET_STREAM);
配置socket地址
localAddress = new LocalSocketAddress(name);
绑定地址
impl.bind(localAddress);
开始监听,并且最大并发数为LISTEN_BACKLOG
impl.listen(LISTEN_BACKLOG);
}
先来一副流程图,方便理解:
先是create创建Socket套接字,流程执行如上截图,重点讲解如上流程图的部分知识:
这个socket创建实质和[C++创建Socket][1]类似,参数也是一样的
Linux.java源码位于:/libcore//luni/src/main/java/libcore/io/Linux.java
Linux_socket源码位于:./libcore//luni/src/main/native/libcore_io_Linux.cpp
在Linux java中定义:
public native FileDescriptor socket(int domain, int type, int protocol) throws ErrnoException;
在libcore_io_Linux.cpp中定义:
static JNINativeMethod gMethods[] = {
省略部分代码
NATIVE_METHOD(Linux, socket, "(III)Ljava/io/FileDescriptor;")
};
void register_libcore_io_Linux(JNIEnv* env) {
jniRegisterNativeMethods(env, "libcore/io/Linux", gMethods, NELEM(gMethods));
}
不难看出,使用了jni的动态注册函数,把libcore/io/Linux这个java类里面的native方法注册进来,具体注册了哪些native函数,在gMethods中存放着,而gMethods使用NATIVE_METHOD宏定义如下:
#define NATIVE_METHOD(className,functionName,signature) \
{ #functionName,signature,reinterpret_cast(className ## _ ## functionName) }
按照上面的socket定义的结果转换为
{"socket", "(III)Ljava/io/FileDescriptor;", (强转为一个函数指针)Linux_socket}
其中#是字符串化,而##则是字符串拼接的意思,这样就解释得通了
最后,在Linux_socket方法中:
static jobject Linux_socket(JNIEnv* env, jobject, jint domain, jint type, jint protocol) {
if (domain == AF_PACKET) {
protocol = htons(protocol); // Packet sockets specify the protocol in host byte order.
}
//socket函数创建套接字
int fd = throwIfMinusOne(env, "socket", TEMP_FAILURE_RETRY(socket(domain, type, protocol)));
//返回套接字的文件描述符
return fd != -1 ? jniCreateFileDescriptor(env, fd) : NULL;
}
绑定逻辑也很简单,最终都是走到C++层的bind函数,执行地址绑定,这里最终绑定的是一个字符串的名字如"server",以后客户端如果需要连接这个服务端,只要指定LocalSocket的服务名字为"server"即可
其逻辑如上类似,都是java封装socket,最后到C++的listen()函数,只是注意LocalServerSocket传递的listen参数是50,说明最大并发支持50个连接数
客户端的读取发送数据过程就不在深入探究,其背后都是走的C++的Socket那一套流程,感兴趣的可以在此基础上继续分析
跨进程数据传递不止Socket可以实现,还有管道、共享内存等等,Android上还特有Binder,那么Socket这一方式其性能如何?和他们比较之?楼主没有深入了解过,猜测其性能应该是最差的一类,猜测依据是因为Socket方式始终是走网络那一套流程,数据要经过网络模块、网卡等转一圈,再跑回来,这样一圈就很耗时,所以性能应该很差,不知道是不是这样,有懂的请留言告知,我们探讨一番!
更多精彩博文,加入我们,一同进步!
[1]:https://www.cnblogs.com/yskn/p/9346570.html