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


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