先說說我的理解: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