前言:介绍一种使用socket通信的方法可以使native和framework自由通信
在Android系统中,java代码和本地代码(c/c++)直接的通信一般是使用jni接口,但是这种方法一般适用于framework层调用native层的代码,但本地代码层(native)又如何把消息传递给上层呢?我们可以借鉴Android中的GSP模块的实现方式来实现native到framework的消息传递,但是比较麻烦。所以我们在这里再介绍另一种方式: socket.
Android是基于linux的系统,系统底层机制基本上是相同的,因为分本地代码和java代码,并且是java代码通过jni调用本地代码执行,所以我们可以把本地代码的执行看成是服务器端的执行,framework端的代码看成是客户端代码。
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())
ref:
http://www.cnblogs.com/bastard/archive/2012/10/09/2717052.html
LocalSocket so = null; LocalSocketAddress addr; so = new LocalSocket(); addr = new LocalSocketAddress(<span style="color:#cc33cc;">SOCKET_NAME</span>, LocalSocketAddress.Namespace.RESERVED); so.connect(addr);如果能正常connect到addr,那就可以像一般文件操作那样进行io读写了。
cli_fd = android_get_control_socket(<span style="color:#993399;">SOCKET_NAME</span>); retval = listen(cli_fd, backlog); cli_fd_cmd = accept(cli_fd, (sockaddr *)&peeraddr, &socklen);
是android 一个字符串常量,在init.rc中定义,
即我们可以通过修改init.rc来改变socket
在android系统源代码目录树里面,有"android/system/core/rootdir/init.rc",
work01@ubuntu:~/hi3716cv200/system/core/rootdir$ ls Android.mk init.environ.rc.in init.trace.rc ueventd.rc etc init.rc init.usb.rc
或者 android_install_folder/out/target/product/xxxx/root
详细: ref:
http://blog.csdn.net/yellow_hill/article/details/39548165
首先
添加一个服务(service),然后,在service下添加一个option 这里就是socket
取名为vdsocketservice_01的 servcie,同时加一个同名的类型为stream的socket,
service vdsocketservice_01 /system/bin/vdsocketservice_01 socket vdsocketservice_01 stream 666 oneshot
在启动vdsocketservice_01 服务时,就会为vdsocketservice_01 分配socket文件系统资源:dev/socket/vdsocketservice_01
vdsocketservice_01 服务的Socket资源和名称vdsocketservice_01 绑定起来。
这些都是在开机初始化化init进程中启动service时完成:
init进程会根据“socket”这个类型从而调用publish_socket(),
service_start create_socket publish_socket
static int s_fdListen = -1;
s_fdListen = android_get_control_socket(SOCKET_NAME_RIL); if (s_fdListen < 0) { RLOGE("Failed to get socket '" SOCKET_NAME_RIL "'"); exit(-1); } ret = listen(s_fdListen, 4); if (ret < 0) { RLOGE("Failed to listen on control socket '%d': %s", s_fdListen, strerror(errno)); exit(-1); }
#include <cutils/sockets.h>
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); } }
/system/bin/vdsocketservice_01就是我们自己的native服务器,在里面我们调用
Java那边只需要使用普通socket API就可以和native服务器通信,但需要注意SOCKET_NAME的值必须和init.rc中的一致,我们这里的SOCKET_NAME为"server",如何编写init.rc请参考android/system/init/readme.txt.
ref:
http://blog.sina.com.cn/s/blog_82f2fc280101395m.html
附录:
1 android init language: 参照andorid的目录下自带的帮助文件 /system/core/init/readme.txt
Android Init Language --------------------- The Android Init Language consists of four broad classes of statements, which are Actions, Commands, Services, and Options.
服务:
Services -------- Services are programs which init launches and (optionally) restarts when they exit. Services take the form of: service <name> <pathname> [ <argument> ]* <option> <option> ...socket 作为option的一种,这里看看帮助文件里面socket的举例:
socket <name> <type> <perm> [ <user> [ <group> ] ] Create a unix domain socket named /dev/socket/<name> and pass its fd to the launched process. <type> must be "dgram", "stream" or "seqpacket". User and group default to 0.
Example init.conf on boot export PATH /sbin:/system/sbin:/system/bin export LD_LIBRARY_PATH /system/lib mkdir /dev mkdir /proc mkdir /sys mount tmpfs tmpfs /dev mkdir /dev/pts <span style="background-color: rgb(51, 255, 51);"> mkdir /dev/socket</span> mount devpts devpts /dev/pts
....
service usbd /system/bin/usbd -r user usbd group usbd socket usbd 666
http://blog.csdn.net/yimiyangguang1314/article/details/6268177
2 socket stream的介绍:
Stream | Supports reliable, two-way, connection-based byte streams without the duplication of data and without preservation of boundaries. ASocket of this type communicates with a single peer and requires a remote host connection before communication can begin. Stream uses the Transmission Control Protocol (Tcp) ProtocolType and the InterNetwork AddressFamily. |
SOCK_STREAM提供面向连接的稳定数据传输,即TCP协议。SOCK_STREAM应用在C语言socket编程中,在进行网络连接前,需要用socket函数向系统申请一个通信端口。socket函数的使用方法如下
ref:
http://baike.baidu.com/view/4785427.htm
http://msdn.microsoft.com/en-us/library/system.net.sockets.sockettype(v=vs.110).aspx
3 ril 的源码和框架结构
http://en.pudn.com/downloads162/sourcecode/comm/modem/detail736165_en.html
ref:
http://calvinlee.github.io/blog/2012/04/26/android-init-socket/
本帖原创,请务必注明转载地址,谢谢!!!