首页 > 代码库 > socketpair

socketpair

int socketpair(int domain, int type, int protocol, int sockfd[2]); //创建未命名的全双工管道

    domain只能为AF_UNIX,也就是限制在本地使用

    type可以是SOCK_STREAM或SOCK_DGRAM,SOCK_STREAM相当于创建了双向流管道,管道的每一端都可以write或read,并且两端的数据流对流是分开的

    protocol必须是0

    sockfd数组返回管道两端的socket描述符

    在2.6.27的内核版本后,type支持了SOCK_CLOEXEC(close on exec )和SOCK_NONBLOCK(非阻塞系统描述符)标志,以节省fcntl系统调用

    socketpair创建的描述符常用于亲缘进程间通信,如父进程调用了socketpair后,父进程再调用fork出子进程,子进程自动继承了描述符(前提是没有close on exec),那么父子进程就可以用sockfd进行通信。

    例子,父进程在sockepair后,再fork出子进程,然后:

#include<sys/types.h>
#include<sys/wait.h>
#include<sys/socket.h>
#include<unistd.h>
#include<iostream>
#include<cstring>
using namespace std;
int main(){
    int fd[2];
    if(socketpair(AF_UNIX,SOCK_STREAM,0,fd)<0)//父进程调用socketpair创建fd数组
        cout<<"socketpair error"<<endl;
    pid_t pid;
    if((pid=fork())<0)
        cout<<"fork error"<<endl;
    else if(pid==0){
        close(fd[0]);//父进程持有fd[0]端,子进程持有fd[1]端
        write(fd[1],"hello parent",strlen("hello parent"));//子进程通过fd[1]向父进程发送消息

        char buf[20];
        while(read(fd[1],buf,20)==-1);//子进程在fd[1]端等待父进程的消息
        buf[13]=‘\0‘;
        cout<<"child receive: "<<buf<<endl;
    }
    else{
        close(fd[1]);
        write(fd[0],"hello child",strlen("hello world"));//父进程通过fd[0]端向子进程发送消息

        char buf[20];
        while(read(fd[0],buf,20)==-1);//父进程在fd[0]端等待子进程的消息
        cout<<"parent receive: "<<buf<<endl;
        wait(NULL);
    }
    return 0;
}

程序输出:

parent receive: hello parent
child receive: hello child
   可见socketpair创建的UNIX域套接字可用于亲缘进程间通信(未命名限制了只能在亲缘进程间使用),在nginx中,master进程就利用socketpair创建套接字然后fork出worker进程,这样master进程和worker进程间就可以利用socketpair产生的套接字通信了。