socketpair创建双向通信的管道(全双工通信)

Linux下socketpair介绍:

   socketpair创建了一对无名的套接字描述符(只能在AF_UNIX域中使用),描述符存储于一个二元数组,例如sv[2] .这对套接字可以进行双工通信,每一个描述符既可以读也可以写。这个在同一个进程中也可以进行通信,向sv[0]中写入,就可以从sv[1]中读取(只能从sv[1]中读取),也可以在sv[1]中写入,然后从sv[0]中读取;但是,若没有在0端写入,而从1端读取,则1端的读取操作会阻塞,即使在1端写入,也不能从1读取,仍然阻塞;

         Linux实现了一个源自BSD的socketpair调用,可以实现在同一个文件描述符中进行读写的功能。该系统调用能创建一对已连接的UNIX族socket。在Linux中,完全可以把这一对socket当成pipe返回的文件描述符一样使用,唯一的区别就是这一对文件描述符中的任何一个都可读和可写,函数原型如下

<span style="font-size:18px;">int socketpair(int d, int type, int protocol, int sv[2]);</span>
参数介绍:
socketpair()函数建立一对匿名的已经连接的套接字,其特性由协议族d、类型type、协议protocol决定,建立的两个套接字描述符会放在sv[0]和sv[1]中。
第1个参数d,表示协议族,只能为AF_LOCAL或者AF_UNIX;
第2个参数type,表示类型,只能为0。
第3个参数protocol,表示协议,可以是SOCK_STREAM或者SOCK_DGRAM。用SOCK_STREAM建立的套接字对是管道流,与一般的管道相区别的是,套接字对建立的通道是双向的,即每一端都可以进行读写。参数sv,用于保存建立的套接字对。

看源码:
/*
 *进程双向通信
 */
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/socket.h>


int main()   
{
    int sv[2];    //一对无名的套接字描述符
    if(socketpair(PF_LOCAL,SOCK_STREAM,0,sv) < 0)   //成功返回零 失败返回-1
    {
	perror("socketpair");
	return 0;
    }

    pid_t id = fork();        //fork出子进程
    if(id == 0)               //孩子
    {
	//close(sv[0]); //在子进程中关闭读
	close(sv[1]); //在子进程中关闭读

	const char* msg = "我是孩子\n";
	char buf[1024];
	while(1)
	{
	   // write(sv[1],msg,strlen(msg));
	    write(sv[0],msg,strlen(msg));
	    sleep(1);

	    //ssize_t _s = read(sv[1],buf,sizeof(buf)-1);
	    ssize_t _s = read(sv[0],buf,sizeof(buf)-1);
	    if(_s > 0)
	    {
		buf[_s] = '\0';
		printf("孩子说 : %s\n",buf);
	    }
	}
    }
    else   //父亲
    {
	//close(sv[1]);//关闭写端口
	close(sv[0]);//关闭写端口
	const char* msg = "我是父亲\n";
	char buf[1024];
	while(1)
	{
	    //ssize_t _s = read(sv[0],buf,sizeof(buf)-1);
	    ssize_t _s = read(sv[1],buf,sizeof(buf)-1);
	    if(_s > 0)
	    {
		buf[_s] = '\0';
		printf("父亲说 : %s\n",buf);
		sleep(1);
	    }
	   // write(sv[0],msg,strlen(msg));
	    write(sv[1],msg,strlen(msg));
	}
    }
    return 0;
}
这里只是代码,整体流程,意思就是,父子进程间正在全双工通信,个人理解即就是同时通信。

代码中有两行一样,一行被注释掉了,这正是说明博文第一段中的话:

向sv[0]中写入,就可以从sv[1]中读取(只能从sv[1]中读取),也可以在sv[1]中写入,然后从sv[0]中读取

整个流程就是,子进程写父进程读和父进程写子进程读同时在进行:上一张图看看:


截取一段代码,两个红色线的方向,都是从一个进程的写到另一个进程的读,同时进行,看运行结果:


打印时,成对打印,双向通信!

赐教!


posted @ 2016-08-06 22:03  云端止水  阅读(6532)  评论(0编辑  收藏