1. 程式人生 > >20-unix域套接字地址結構

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,說明這是一個套接字檔案。