socketpair的问题

今天跟人谈到socketpair的问题,晚上回来写了个程序验证下自己的猜测!

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

      验证所用代码:

    #include <stdio.h> 
    #include <string.h> 
    #include <unistd.h> 
    #include <sys/types.h> 
    #include <error.h> 
    #include <errno.h> 
    #include <sys/socket.h> 
    #include <stdlib.h> 
     
    #define BUF_SIZE 30 
     
    int main(){ 
            int s[2]; 
            int w,r; 
            char * string = "This is a test string"; 
            char * buf = (char*)calloc(1 , BUF_SIZE); 
     
            if( socketpair(AF_UNIX,SOCK_STREAM,0,s) == -1 ){ 
                    printf("create unnamed socket pair failed:%s\n",strerror(errno) ); 
                    exit(-1); 
            } 
     
            /*******test in a single process ********/ 
            if( ( w = write(s[0] , string , strlen(string) ) ) == -1 ){ 
                    printf("Write socket error:%s\n",strerror(errno)); 
                    exit(-1); 
            } 
            /*****read*******/ 
            if( (r = read(s[1], buf , BUF_SIZE )) == -1){ 
                    printf("Read from socket error:%s\n",strerror(errno) ); 
                    exit(-1); 
            } 
            printf("Read string in same process : %s \n",buf); 
              if( (r = read(s[0], buf , BUF_SIZE )) == -1){ 
                              printf("Read from socket s0 error:%s\n",strerror(errno) ); 
                                              exit(-1); 
                                                      } 
                                                      printf("Read from s0 :%s\n",buf); 
     
            printf("Test successed\n"); 
            exit(0); 
    } 

  若fork子进程,然后在服进程关闭一个描述符eg. s[1] ,在子进程中再关闭另一个 eg. s[0]    ,则可以实现父子进程之间的双工通信,两端都可读可写;当然,仍然遵守和在同一个进程之间工作的原则,一端写,在另一端读取;

     这和pipe有一定的区别,pipe是单工通信,一端要么是读端要么是写端,而socketpair实现了双工套接字,也就没有所谓的读端和写端的区分

验证代码:


    #include <stdio.h> 
    #include <string.h> 
    #include <unistd.h> 
    #include <sys/types.h> 
    #include <error.h> 
    #include <errno.h> 
    #include <sys/socket.h> 
    #include <stdlib.h> 
     
    #define BUF_SIZE 30 
     
    int main(){ 
            int s[2]; 
            int w,r; 
            char * string = "This is a test string"; 
            char * buf = (char*)calloc(1 , BUF_SIZE); 
            pid_t pid; 
     
            if( socketpair(AF_UNIX,SOCK_STREAM,0,s) == -1 ){ 
                    printf("create unnamed socket pair failed:%s\n",strerror(errno) ); 
                    exit(-1); 
            } 
     
            /***********Test : fork but don't close any fd in neither parent nor child process***********/ 
            if( ( pid = fork() ) > 0 ){ 
                    printf("Parent process's pid is %d\n",getpid()); 
                 close(s[1]); 
                    if( ( w = write(s[0] , string , strlen(string) ) ) == -1 ){ 
                            printf("Write socket error:%s\n",strerror(errno)); 
                            exit(-1); 
                    } 
            }else if(pid == 0){ 
                    printf("Fork child process successed\n"); 
                    printf("Child process's pid is :%d\n",getpid()); 
                    close(s[0]); 
            }else{ 
                    printf("Fork failed:%s\n",strerror(errno)); 
                    exit(-1); 
            } 
     
            /*****read***In parent and child****/ 
            if( (r = read(s[1], buf , BUF_SIZE )) == -1){ 
                    printf("Pid %d read from socket error:%s\n",getpid() , strerror(errno) ); 
                    exit(-1); 
            } 
            printf("Pid %d read string in same process : %s \n",getpid(),buf); 
            printf("Test successed , %d\n",getpid()); 
            exit(0); 
    } 

以上代码中在父子进程之间各关闭了一个描述符,则在父进程写可从子进程读取,反之若子进程写,父进程同样可以读取;大家可以验证下

另外,我也测试了在父子进程中都不close(s[1]),也就是保持两个读端,则父进程能够读到string串,但子进程读取空串,或者子进程先读了数据,父进程阻塞于read操作!

 

之所以子进程能读取父进程的string,是因为fork时,子进程继承了父进程的文件描述符的,同时也就得到了一个和父进程指向相同文件表项的指针;若父子进程均不关闭读端,因为指向相同的文件表项,这两个进程就有了竞争关系,争相读取这个字符串.父进程read后将数据转到其应用缓冲区,而子进程就得不到了,只有一份数据拷贝(若将父进程阻塞一段时间,则收到数据的就是子进程了,已经得到验证,让父进程sleep(3),子进程获得string,而父进程获取不到而是阻塞)

本文出自 “流离and逍遥” 博客,请务必保留此出处http://liulixiaoyao.blog.51cto.com/1361095/533469


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章