天天看點

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;
 }
           

編譯運作結果

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

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

繼續閱讀