Linux本地套接字(Unix域套接字)----SOCK_DGRAM方式

目錄

 

簡述

創建服務端代碼:

創建客戶端代碼

接收函數封裝

發送封裝

服務端測試main函數

客戶端測試main函數

編譯運行結果


簡述

這裏介紹一下Linux進程間通信的socket方式---Local socket。這篇主要是介紹下SOCK_DGRAM方式的通信,即數據包的方式(與UDP類似),面向無連接。

這個代碼是我剛開始學的時候寫的,代碼比較簡單,適合初學,學習最快的方式就是直接拿源碼修改、編譯運行、調試。

完整源代碼:https://gitee.com/fensnote/demo_code/tree/master/Linux/unix_socket

 

創建服務端代碼:

int startServer()
{
    int iRet;

	TSockAddrUn serv_unadr;
	TSockAddrIn serv_inadr;
	TSockAddr   *pSockAddr = NULL;

	bzero(&serv_unadr,sizeof(serv_unadr));
	bzero(&serv_inadr,sizeof(serv_inadr));

	serv_unadr.sun_family = AF_UNIX;
	strcpy(serv_unadr.sun_path,UNIX_SOCKET_PATH);

	pSockAddr = (TSockAddr *)&serv_unadr;
	
	signal(SIGPIPE, SIG_IGN);


	/* 創建本地socket */
	sockFd = socket(AF_UNIX, SOCK_DGRAM, 0);//數據包方式
	if ( sockFd <= 0)
	{
	    perror("socket error");
	    return sockFd;
	}

	/* 綁定監聽口 */
    int flag = 1;
    iRet = setsockopt(sockFd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));

    setSocketAttr(sockFd);

    unlink(UNIX_SOCKET_PATH);
	iRet = bind(sockFd, pSockAddr, sizeof(TSockAddr));
	if (iRet != 0)
	{
	    perror("bind error");
		close(sockFd);
		return -1;
	}


    return sockFd;
}

創建客戶端代碼

面向無連接的方式,和服務端的代碼差別不大:

int InitUdpClient()
{

	TSockAddrUn unadr;
	TSockAddr   *pSockAddr = NULL;

	bzero(&unadr,sizeof(unadr));

	char tmpPath[] = "/tmp/unix_XXXX";
	char *tmpName = mktemp(tmpPath);

	unadr.sun_family = AF_LOCAL;
	strcpy(unadr.sun_path, tmpName);

	pSockAddr = (TSockAddr *)&unadr;


	/* 創建本地socket */
	sockFd = socket(AF_LOCAL, SOCK_DGRAM, 0);//數據包方式
	if ( sockFd <= 0)
	{
	    perror("CUdpClient:: socket error");
	    return sockFd;
	}
	
	unlink(tmpPath);

	/* 綁定監聽口 */
    //setSocketAttr(sockFd);
	int iRet = bind(sockFd,pSockAddr, sizeof(TSockAddr));
	if (iRet != 0)
	{
	    perror("bind error");
		close(sockFd);
		return -1;
	}

    return sockFd;
}

接收函數封裝

//返回0 超時  timeOut-超時時間
int UnixRead(char *recvBuf, int len, int timeOut)
{
	int nRead = readable_timeo(sockFd, timeOut);
	if ( nRead <= 0 )
	{
		printf("UnixRead, read time out!\n");
		return 0;
	}

	pSockAddr = (TSockAddr *)&unClientaddr;
	socklen  = sizeof(TSockAddrUn);

	bzero(recvBuf, len);
	
	nRead = recvfrom(sockFd, recvBuf, len, 0, pSockAddr, &socklen);
	if ( nRead <= 0 )
	{
		if ( (EAGAIN == errno) || (EINTR == errno))
		{
			return 0;   //接收連接超時
		}

		perror("UnixRead read error:");
	}
	
	return nRead;
}

發送封裝

int UnixSend(const void *data, int len)
{
	TSockAddrUn unadr;
	TSockAddr   *pSockAddr = NULL;

	bzero(&unadr,sizeof(unadr));
	
	unadr.sun_family = AF_LOCAL;
	strcpy(unadr.sun_path, UNIX_SOCKET_PATH);

	pSockAddr = (TSockAddr *)&unadr;
	socklen_t socklen  = sizeof(TSockAddrUn);

	return sendto(sockFd, data, len, 0, pSockAddr, socklen);
}

服務端測試main函數

int main()
{
	startServer();
	int nRead = 0;
	
	
	char recvBuf[1024] = {0}; 	
	
	while(1)
	{		
		nRead = UnixRead(recvBuf, 1024, 5);
		if ( nRead <= 0 )
		{
			continue;
		}
		else
		{
			printf("recv %d data: %s\n",nRead, recvBuf);
			const char *sendMsg = "svr ack!";
			UnixSend(sendMsg, strlen(sendMsg));
		}
		
		sleep(1);
	}
	
	
	
	return 0;
}

客戶端測試main函數

 int main(  )
 {
	 int sockFd = InitUdpClient();
	 
	 int nRead = 0;

	 const char *sendMsg = "hello";
	 char recvBuf[1024] = {0};
	 while(1)
	 {
			
		nRead = UnixSend(sendMsg, strlen(sendMsg));
		printf("send %d data: %s\n", nRead, sendMsg);
	
		nRead = UnixRead(recvBuf, 1024, 5);
		printf("recv %d data: %s\n", nRead, recvBuf);
		sleep(2);
	 }
	 return 0;
 }

編譯運行結果

左邊是服務端,右邊是客戶端。

 

給人微信公衆號:

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