20-unix域套接字地址結構

1. unix域協議

看到這個標題,不知道的小夥伴肯定以爲這是一個協議族之類的,但實際上unix域協議是在單臺主機上客戶端與服務端之間的通信方法,簡單來說,unix域協議也是一種進程間通信方式,用於同一臺主機上的客戶端和服務端,爲不同的進程間傳遞描述符。

通常在同一臺主機上,使用unix域套接字通常比TCP套接字效率更高,同時unix域套接字還可以用於在進程間傳遞描述符等等。

那麼unix域套接字是如何在進程間傳遞描述符的?爲了弄明白這個問題,我們需要繼續學習unix域協議的其他知識,先從如何構建一個unix域套接字地址結構開始吧。

 

2. unix域套接字地址結構

 

unix域套接字的地址結構定義在<sys/un.h>文件中,具體信息如下:

struct sockaddr_un {
  unsigned short int sun_family;         //  AF_UNIX或者AF_LOCAL
  char sun_path[108];                    //  文件路徑
}

在不同的linux系統中sun_path數組的大小是不同的,在早期BSDB版本中sun_path數組大小爲108字節,而POSIX規範中卻沒有定義sun_path數組的大小,但是我們可以使用sizeof運算符得出sockaddr_un結構體的大小,來驗證這個文件路徑是否合適存放在sun_path數組中。

注意:創建的套接口文件最好爲絕對路徑,建議指定在/tmp目錄下,因爲POSIX規範對於unix域套接字的相對路徑名將導致未定義行爲,這是出於爲了方便移植的考慮。另外,存放文件路徑的sun_path數組必須以空字符(即’\0’字符)結尾,而sum_family成員用於指定成AF_UNIX或AF_LOCAL。

 

3. 綁定unix域套接字示例

 

下面的程序是創建一個unix 域套接字,然後調用bind綁定一個文件路徑名,再調用getsockname輸出這個路徑名:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/un.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(int argc , char **argv)
{
	int sockfd;
	socklen_t len;
	struct sockaddr_un addr1 , addr2;
	if(argc != 2){
		puts("usage: unixbind <pathname>");
		exit(-1);
	}

	//指定AF_LOCAL,最後一個參數默認爲0
	sockfd = socket(AF_LOCAL , SOCK_STREAM , 0);

	//刪除文件路徑
	unlink(argv[1]);

	bzero(&addr1 , sizeof(addr1));

	//創建unix域套接字
	addr1.sun_family = AF_LOCAL;
	strncpy(addr1.sun_path , argv[1] , sizeof(addr1.sun_path)-1);
	
	//綁定unix域套接字
	bind(sockfd , (struct sockaddr*)&addr1 , SUN_LEN(&addr1));

	//獲取unix域套接字
	len = sizeof(addr2);
	getsockname(sockfd, (struct sockaddr*)&addr2, &len);
	//打印獲取到的unix與套接字信息
	printf("bound name = %s , returned len = %d\n" , addr2.sun_path , len);
	return 0;
}

分析以上代碼:

如果sun_path中指定的文件路徑存在,那麼調用bind綁定unix域套接字就會失敗,因此這裏調用unlink把文件路徑刪除掉,如果文件路徑不存在,則忽略unlink函數返回的錯誤。

使用strncpy函數複製文件路徑,避免文件路徑過長導致sun_path溢出,然後初始化sum_path並減1是爲了保證sum_path數組以‘\0’字符結尾。

 

執行結果:

從上面的執行結果來看,getsockname返回的大小是12,其中sun_family佔2字節,文件路徑佔10字節。通過ls -l命令可以看到文件類型是S,說明這是一個套接字文件。

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