全双工管道
全双工管道需要双向通信,使用两个独立的数据流,故需要两个半双工管道实现实现全双工,每个方向一个。
因为一个管道只存在一个缓冲区,写入管道的任何数据都添加到该缓冲区的末尾,从管道读出的都是取自该缓冲区开头的数据。
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/socket.h>
int main(int argc,char *argv[])
{
int fd[2],n;
char c;
pid_t childpid;
//pipe(fd); pipe创建的fd[0]/fd[1]一端只能读或者写。
/*
int socketpair(int domain, int type, int protocol, int sv[2]);
socketpair()函数建立一对匿名的已经连接的套接字,
其特性由协议族d、类型type、协议protocol决定,建立的两个套接字描述符会放在sv[0]和sv[1]中。
可以实现在同一个文件描述符中进行读写的功能。 fd[0]/fd[1]一端既能读又能写。
socketpair函数参数说明:
第1个参数domain,表示协议族,只能为AF_LOCAL或者AF_UNIX。
第2个参数type,表示协议,可以是SOCK_STREAM或者SOCK_DGRAM。
用SOCK_STREAM建立的套接字对是管道流,与一般的管道相区别的是,套接字对建立的通道是双向的,
即每一端都可以进行读写。
第3个参数protocol,表示类型,只能为0。
第4个参数sv[2]是接收代表两个套接口的整数数组。每一个文件描述符代表一个套接口,并且与另一个并没有区别。
*/
socketpair(AF_UNIX, SOCK_STREAM, 0, fd);//if donot set this option,it won't work properly.
if((childpid = fork()) == 0) /*子进程*/
{
sleep(3);/*子进程先休眠一段时间,让父进程的read先于子进程的read执行,从而查看父进程是否读回自己刚写的字符*/
if((n = read(fd[0],&c,1)) != 1)/*子进程从管道中读取字符*/
printf("child:read return %d\n",n);
printf("child read %c\n",c);
write(fd[0],"c",1);/*子进程将字符c写入管道*/
exit(0);
}
/*父进程*/
write(fd[1],"p",1);/*父进程先将字符p写入管道*/
if((n = read(fd[1],&c,1)) !=1 )/*阻塞在此,等待子进程写入*/
printf("parent:read return %d",n);
printf("parent read %c\n",c);
exit(0);
}