Android中LocalSocket(套接字)使用
今天在看《Android框架揭秘》的第5章《Zygote》时,Zygote在初始化时,会调用registerZygoteSocket()来接收新的Android应用程序运行的请求,
从字面来理解是传统的Socket使用,但个人觉得不应该是,特地找资料学习了一下,下面的介绍比较详细到位。
又进一步了解一下,使用的其实是UDS(Unix Domain Socket),详细的介绍如下:
linux操作系统提供了一种UNIX域协议的进程间通信方式,它不能应用在网络中,能使用在本机两进程间的通信中。它能方便的向两个非亲属关系的进程间传递文件描述符,效果类似于在父子进程间传递一样。UNIX域套接字在和本地进程进行交互时候效率更高,因为它不需要处理网络异常可能。
socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIX Domain Socket。虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是UNIX Domain Socket用于IPC更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。UNIX Domain Socket也提供面向流和面向数据包两种API接口,类似于TCP和UDP,但是面向消息的UNIX Domain Socket也是可靠的,消息既不会丢失也不会顺序错乱。
UNIX Domain Socket是全双工的,API接口语义丰富,相比其它IPC机制有明显的优越性,目前已成为使用最广泛的IPC机制,比如X Window服务器和GUI程序之间就是通过UNIX Domain Socket通讯的。
使用UNIX Domain Socket的过程和网络socket十分相似,也要先调用socket()创建一个socket文件描述符,address family指定为AF_UNIX,type可以选择SOCK_DGRAM或SOCK_STREAM,protocol参数仍然指定为0即可。
UNIX Domain Socket与网络socket编程最明显的不同在于地址格式不同,用结构体sockaddr_un表示,网络编程的socket地址是IP地址加端口号,而UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的路径,这个socket文件由bind()调用创建,如果调用bind()时该文件已存在,则bind()错误返回。
原文链接:http://www.cnblogs.com/bastard/archive/2012/10/09/2717052.html
一 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
- <span style="font-family:Microsoft YaHei;">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);
- }
- }</span>
3 framework层
客户端程序:
\frameworks\base\services\java\com\android\server\pm\Installer.java
- <span style="font-size:12px;"><span style="font-family:Microsoft YaHei;">boolean connect()
- {
- //创建socket
- mSocket = new LocalSocket();
- //设置连接地址
- LocalSocketAddress address = new LocalSocketAddress("installd",
- LocalSocketAddress.Namespace.RESERVED);
- //建立连接
- mSocket.connect(address);
- //获取数据输入流 可以读数据
- mIn = mSocket.getInputStream();
- //获取数据输出流 可以写数据
- mOut = mSocket.getOutputStream();
- }</span></span>
因此以native层service与framework建立client/server模式socket通信主要代码:
java层主要代码:
- <span style="font-size:12px;"><span style="font-family:Microsoft YaHei;">LocalSocket s =null;
- LocalSocketAddress l;
- s = new LocalSocket();
- l = new LocalSocketAddress(SOCKET_NAME,
- LocalSocketAddress.Namespace.RESERVED);
- s.connect(l);</span></span>
native层主要代码:
- <span style="font-family:Microsoft YaHei;"> s_fdListen = android_get_control_socket(SOCKET_NAME);
- ret = listen(s_fdListen, n);
- s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen);</span>
init.rc中加入:
- <span style="font-family:Microsoft YaHei;">service myserver /system/bin/myserver
- class main
- socket myserver stream 600 system system
- ……</span>
系统提供了LocalSocket作为客户端使用,同时提供了LocalServerSocket作为服务端使用。
Zygote服务使用了LocalServerSocket作为服务端socket通信。
建立socket通信,也可以在代码执行过程中进行,使用LocalSocket与LocalServerSocket。
在init.rc中为服务端建立的socket资源和初始化时绑定,与在代码中使用LocalServerSocket
建立的服务端socket资源在Linux域空间不同而已,过程是一样的跟一般的socket通信过程一致。
四 LocalSocket与LocalServerSocket建立socket通信
LocalSocket就是作为客户端建立于服务端的连接,发送数据。
LocalServerSocket作为服务端使用,建立socket监听客户端请求。通过构造函数看到有两种方式:
在Linux抽象空间 创建一个新的服务端socket:
- <span style="font-family:Microsoft YaHei;">public LocalServerSocket(String name) throws IOException{ //创建socket资源
- impl = new LocalSocketImpl(); impl.create(true); //绑定地址
- localAddress = new LocalSocketAddress(name);
- impl.bind(localAddress); //监听 impl.listen(LISTEN_BACKLOG);
- }</span>
用文件描述符创建已经存在并且绑定的服务端socket:
如在init.rc中指定socket资源 dev/socket/……,zygote使用此方式创建作为服务端的socket
LocalServerSocket socket = new LocalServerSocket(createFileDescriptor(fileDesc));
- <span style="font-size:12px;"><span style="font-family:Microsoft YaHei;">public LocalServerSocket(FileDescriptor fd) throws IOException{ //已绑定 监听
- impl = new LocalSocketImpl(fd);
- impl.listen(LISTEN_BACKLOG);
- localAddress = impl.getSockAddress();
- }
- </span></span>
通常使用过程中:
客户端代码:
- <span style="font-family:Microsoft YaHei;">String message;//创建socketLocalSocket sender = new LocalSocket();//建立对应地址连接
- sender.connect(new LocalSocketAddress(SOCKET_ADDRESS));//发送写入数据
- sender.getOutputStream().write(message.getBytes());//关闭socket
- sender.getOutputStream().close();</span>
服务端:
- <span style="font-family:Microsoft YaHei;">//创建socket并绑定监听 新创建的
- LocalServerSocket server = new LocalServerSocket(SOCKET_ADDRESS);
- while (true) {
- //等待建立连接 LocalSocket receiver = server.accept(); //接收获取数据流
- InputStream input = receiver.getInputStream();
- ……
- }</span>
UDS(Unix Domain Socket)的进一步了解,可以参考此文:
Android中LocalSocket(套接字)使用相关推荐
- 浅析C#中的套接字编程
套接字基本概念: 套接字是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元.可以将套接字看作不同主机间的进程进行双向通信的端点,它构成了单个主机内及整个网络间的编程界面.套接字存在于通信域中 ...
- python socket自动重连_详解python3中socket套接字的编码问题解决
一.TCP 1.tcp服务器创建 #创建服务器 from socket import * from time import ctime #导入ctime HOST = '' #任意主机 PORT = ...
- C#中的套接字编程(一) --转
TCP/IP 体系结构与特点 TCP/IP协议实际上就是在物理网上的一组完整的网络协议.其中TCP是提供传输层服务,而IP则是提供网络层服务.TCP/IP包括以下协议: IP:网间协议 ...
- 什么是Python中的套接字编程?
摘要:本文涵盖了有关使用Python进行套接字编程的所有领域.套接字可以帮助您建立这些连接,而Python无疑可以简化连接. 本文分享自华为云社区<从零开始学python | 什么是Python ...
- Android中LocalSocket使用
一 Socket Socket最初用在基于TCP/IP网络间进程通信中,以客户端/服务器模式进行通信. 实现异步操作,共享资源集中处理,提高客户端响应能力. Tcp通信基本流程: 服务器端 ...
- nodejs入门_如何在NodeJS中使用套接字创建专业的Chat API解决方案[入门级]
nodejs入门 Have you ever wondered how chat applications work behind the scenes? Well, today I am going ...
- python socket send_全网最详细python中socket套接字send与sendall的区别
将数据发送到套接字. 套接字必须连接到远程套接字. 返回发送的字节数. 应用程序负责检查是否已发送所有数据; 如果仅传输了一些数据, 则应用程序需要尝试传递剩余数据.(需要用户自己完成) 将数据发送 ...
- python socket 域名_Python网络编程中的套接字名和DNS解析。
距离上一次TCP的文章,这一次要讲的是套接字名和DNS,并且还会涉及到网络数据的发送接受和网络错误的发生和处理. 下面说套接字名,在创建和部署每个套接字对象时总共需要做5个主要的决定,主机名和IP地址 ...
- Python中的套接字编程
文章目录 **连接到服务器:** **一个简单的服务器客户端程序:** **服务器** **客户端** 套接字编程是一种连接网络上的两个节点以相互通信的方法.一个套接字(节点)侦听 IP 处的特定端口 ...
最新文章
- lsof/netstat命令的一个重要作用: 根据进程查端口, 根据端口查进程
- SAP CRM Fiori应用Simulation pipeline里dualSlider的实现
- Docker最全教程之使用Tencent Hub来完成CI(十)
- 学习较底层编程:动手写一个C语言编译器
- 进一步的去了解正则[一]
- 【Win 10 应用开发】分析 URI 中的查询字符串
- 20175320 2018-2019-2 《Java程序设计》第6周学习总结
- linux 访问windows 共享文件
- 改变权限Linux,Linux chmod改变权限属性命令
- Security+ 学习笔记32 云安全控制
- 机房管理制度(试行)
- android系统解锁,android 调用系统解锁方法
- 鸿蒙充值卡是不是真的,鸿蒙成仙录红包版
- 俄罗斯方块游戏设计与实现
- coreldraw x7 分布_CDR X7新增功能有哪些,CDR X7新功能介绍
- 网易人工智能受邀出席第二届云创大会
- 大众点评 爬虫 python_[Python爬虫练习]大众点评会员榜
- H3C IRF2典型应用
- Dinic算法 (优化)
- 万能地图下载器八种新建地图下载任务的方法
热门文章
- cad中tk什么意思_原来CAD里的这些缩写是这个意思!终于搞懂了对象捕捉这个玩意儿...
- 在线解析xml,json数据的网址
- 29个习惯让你的拖延症一去不复返
- 彩虹代刷源码+支付接口 搭建教程
- 100种思维模型之损失规避思维模型-008
- 采用超级电容器单独供电的BLDC调速控制系统设计分析与实现
- 整体思路【路由权限管理方案】
- Android辅助工具,G分助手的实现 - 心悦俱乐部app自动签到、领G分
- php判断花呗扫码支付,为啥支付宝“诱导”用户,首选花呗付款?答案已经确认了...
- 云桌面服务器资源计算机,从“云桌面”认识“云计算”