zoukankan      html  css  js  c++  java
  • 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;
     }

    编译运行结果

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

  • 相关阅读:
    [置顶] Android中定时器的3种实现方法
    [置顶] Android代码应用程序通过WakeLock保持后台唤醒状态
    [置顶] 当爱情遇上互联网
    [置顶] Android咨询阿米巴基金合伙人李治国:我为什么投资快的打车?
    [置顶] Android问题Getting Android Sensor Events While The Screen is Off
    静态SQL和动态SQL
    IBM Data Studio使用对象创建的双引号/大小写问题以及表/列重命名
    DB2数据库查询过程(Query Processing)统计信息与过滤因子(Statistics and Filter Factors)
    DB2数据库查询过程(Query Processing)概述
    DB2数据库查询过程(Query Processing)表扫描与I/O(Table Scan and I/O)
  • 原文地址:https://www.cnblogs.com/fensnote/p/13436451.html
Copyright © 2011-2022 走看看