• 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!
    ");
    		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
    ",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
    ", nRead, sendMsg);
    	
    		nRead = UnixRead(recvBuf, 1024, 5);
    		printf("recv %d data: %s
    ", nRead, recvBuf);
    		sleep(2);
    	 }
    	 return 0;
     }

    编译运行结果

    左边是服务端,右边是客户端。

  • 相关阅读:
    JAVA中内存分配策略里的堆与栈
    Java中间件:淘宝网系统高性能利器
    优化Java堆大小的五个技巧
    Java编程程序异常处理方法
    Java内存管理的九个小技巧
    c++ 函数模板
    c setsockopt设置套接字状态
    c++ typedef 类型重定义语句
    c getaddrinfo函数
    c iovec结构体 readv writev
  • 原文地址:https://www.cnblogs.com/fensnote/p/13436451.html
Copyright © 2020-2023  润新知