socketpair創建雙向通信的管道(全雙工通信)


Linux下socketpair介紹:

   socketpair創建了一對無名的套接字描述符(只能在AF_UNIX域中使用),描述符存儲於一個二元數組,例如sv[2] .這對套接字可以進行雙工通信,每一個描述符既可以讀也可以寫。這個在同一個進程中也可以進行通信,向sv[0]中寫入,就可以從sv[1]中讀取(只能從sv[1]中讀取),也可以在sv[1]中寫入,然后從sv[0]中讀取;但是,若沒有在0端寫入,而從1端讀取,則1端的讀取操作會阻塞,即使在1端寫入,也不能從1讀取,仍然阻塞;

         Linux實現了一個源自BSD的socketpair調用,可以實現在同一個文件描述符中進行讀寫的功能。該系統調用能創建一對已連接的UNIX族socket。在Linux中,完全可以把這一對socket當成pipe返回的文件描述符一樣使用,唯一的區別就是這一對文件描述符中的任何一個都可讀和可寫,函數原型如下

<span style="font-size:18px;">int socketpair(int d, int type, int protocol, int sv[2]);</span>
參數介紹:
socketpair()函數建立一對匿名的已經連接的套接字,其特性由協議族d、類型type、協議protocol決定,建立的兩個套接字描述符會放在sv[0]和sv[1]中。
第1個參數d,表示協議族,只能為AF_LOCAL或者AF_UNIX;
第2個參數type,表示類型,只能為0。
第3個參數protocol,表示協議,可以是SOCK_STREAM或者SOCK_DGRAM。用SOCK_STREAM建立的套接字對是管道流,與一般的管道相區別的是,套接字對建立的通道是雙向的,即每一端都可以進行讀寫。參數sv,用於保存建立的套接字對。

看源碼:
/*
 *進程雙向通信
 */
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/socket.h>


int main()   
{
    int sv[2];    //一對無名的套接字描述符
    if(socketpair(PF_LOCAL,SOCK_STREAM,0,sv) < 0)   //成功返回零 失敗返回-1
    {
	perror("socketpair");
	return 0;
    }

    pid_t id = fork();        //fork出子進程
    if(id == 0)               //孩子
    {
	//close(sv[0]); //在子進程中關閉讀
	close(sv[1]); //在子進程中關閉讀

	const char* msg = "我是孩子\n";
	char buf[1024];
	while(1)
	{
	   // write(sv[1],msg,strlen(msg));
	    write(sv[0],msg,strlen(msg));
	    sleep(1);

	    //ssize_t _s = read(sv[1],buf,sizeof(buf)-1);
	    ssize_t _s = read(sv[0],buf,sizeof(buf)-1);
	    if(_s > 0)
	    {
		buf[_s] = '\0';
		printf("孩子說 : %s\n",buf);
	    }
	}
    }
    else   //父親
    {
	//close(sv[1]);//關閉寫端口
	close(sv[0]);//關閉寫端口
	const char* msg = "我是父親\n";
	char buf[1024];
	while(1)
	{
	    //ssize_t _s = read(sv[0],buf,sizeof(buf)-1);
	    ssize_t _s = read(sv[1],buf,sizeof(buf)-1);
	    if(_s > 0)
	    {
		buf[_s] = '\0';
		printf("父親說 : %s\n",buf);
		sleep(1);
	    }
	   // write(sv[0],msg,strlen(msg));
	    write(sv[1],msg,strlen(msg));
	}
    }
    return 0;
}
這里只是代碼,整體流程,意思就是,父子進程間正在全雙工通信,個人理解即就是同時通信。

代碼中有兩行一樣,一行被注釋掉了,這正是說明博文第一段中的話:

向sv[0]中寫入,就可以從sv[1]中讀取(只能從sv[1]中讀取),也可以在sv[1]中寫入,然后從sv[0]中讀取

整個流程就是,子進程寫父進程讀和父進程寫子進程讀同時在進行:上一張圖看看:


截取一段代碼,兩個紅色線的方向,都是從一個進程的寫到另一個進程的讀,同時進行,看運行結果:


打印時,成對打印,雙向通信!

賜教!

 
        


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM