本文主要详细介绍了Android socketpair双向通信的相关信息,有一定的参考价值,感兴趣的朋友可以参考一下。
Android很多地方都涉及到进程间通信,比如输入系统,那么进程间通信会涉及到什么呢?
1.进程:负责读取和分发事件。
2.应用程序:负责处理输入事件。
这两个过程将涉及哪些双向沟通:
1.该流程发送输入事件。
2.应用程序将通知事件已被处理或应用程序已被关闭。
这里你可能会疑惑,binder系统能实现上面说的双向通信吗?
答案是否定的。binder分为服务器端和客户端。每次客户端发起请求,服务器收到请求后回复。这样做的缺点是每个请求只能单方面发起,服务器无法主动向客户端发送数据,自然不能称为双向通信。
所以这里我们介绍一个新的方法叫做“socketpair”
通过调用socketpair应用程序可以获得两个文件句柄。假设这两个文件句柄是fd1和fd2,那么这两个文件都应该有两个缓冲区(send_buf和rcv_buf)。当一个进程或线程通过fd1写自己的send_buf时,内核中的socket会将send_buf中的数据写入fd2的rcv_buf中,另一个线程或进程可以读取FDD。
但是它也有缺点:既然通信是通过创建一个文件句柄来访问这个句柄实现的,那么谁能看到这个句柄呢?只有当前APP创建的线程或者其子进程才能看到这些文件句柄,所以只适用于线程间通信或者有亲缘关系的进程间通信(父子进程)。
那么如果想用socketpair实现任意进程间的双向通信呢?
假设现在有APP1和APP2,这两个APP想要任意通信,那么APP2需要获取APP1的fd2。你是怎么得到它的?可以通过binder进行通信,将fd2传递给APP2。当然在APP2中变成了fd3,这样APP2这个任意进程就可以通过socketpair进行通信了。本文将不解释binder的实现。
下面我们来解释一下“Socketpair”的过程和用法:
#include pthread.h
#包括unistd.h
#包含stdio.h
#include sys/types.h /*参见注释*/
#包含sys/socket.h
#定义套接字缓冲区大小(32768U)
/*参考:
* frameworks \ native \ libs \ input \ input transport . CPP
*/
/*线程1函数实现*/
void *函数_线程1(void *参数)
{
int FD=(int)arg;/*转换文件句柄*/
char buf[500];
int len
int CNT=0;
while (1)
{
/*发出:你好,主线程*/
len=sprintf(buf,' Hello,主线程,cnt=%d ',CNT);
write(fd,buf,len);
/*读取数据(主线程发回的数据)*/
len=read(fd,buf,500);
buf[len]=' \ 0 ';
printf('%s\n ',buf);
/*延迟5秒*/
睡眠(5);
}
返回NULL
}
int main(int argc,char **argv)
{
int套接字[2];
/*使用socketpair获得数组套接字的两个文件句柄*/
socketpair(AF_UNIX,SOCK_SEQPACKET,0,sockets);
/*设置缓冲区,每个文件句柄对应两个缓冲区,两个文件对应四个*/
int BUFFER SIZE=SOCKET _ BUFFER _ SIZE;
setsockopt(sockets[0],SOL_SOCKET,SO_SNDBUF,bufferSize,sizeof(buffer size));
setsockopt(sockets[0],SOL_SOCKET,SO_RCVBUF,bufferSize,sizeof(buffer size));
setsockopt(sockets[1],SOL_SOCKET,SO_SNDBUF,bufferSize,sizeof(buffer size));
setsockopt(sockets[1],SOL_SOCKET,SO_RCVBUF,bufferSize,sizeof(buffer size));
/*创建线程1(thread1)并将文件句柄套接字[1]传递给子线程thread1 */
pthread _ t threadID
pthread_create(threadID,NULL,function_thread1,(void *)sockets[1]);
char buf[500];
int len
int CNT=0;
int FD=sockets[0];/*当前主函数的文件句柄是sockets[0] */
while(1)
{
/*读取数据:读取线程1发送的数据*/
len=read(fd,buf,500);
buf[len]=' \ 0 ';
printf('%s\n ',buf);
/*主线程发送给thread1: Hello,thread1 */
len=sprintf(buf,' Hello,thread1,cnt=%d ',CNT);
write(fd,buf,len);
}
}
程序很简单。首先,使用socketpair获取两个文件句柄并设置发送和接收缓冲区,然后创建另一个线程。在线程中,通过文件句柄向主线程读写数据。mian也执行相同的操作来实现双向通信。
测试:
检查这两个线程是否存在:
我们也可以修改程序,让应用分叉出一个子进程,然后让父子进程通过socketpair实现双向通信。比较简单,这里就不赘述了。
因为socekpair只适合线程间通信,或者有亲缘关系,所以如果要实现任意两个进程之间的双向通信,就需要使用binder系统将fd转移到另一个进程。在这里,简要描述如下过程:
使用活页夹传输文件句柄:
假设APP1,打开一个文件句柄获取fd1。
文件结构,即files-fdt-fd[fd1],由binder驱动程序根据fd1获取。
从APP2的files-fdt-fd中取一个空项,假设是fd2,让fd2指向fd1的文件结构,即files-fdt-fd[fd2]=file。
之后,APP1可以通过fd1访问同一个文件,APP2可以通过fd2访问同一个文件。
这就是本文的全部内容。希望对大家的学习有帮助,支持我们。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。