目录
简述
这里介绍一下Linux进程间通信的socket方式---Local socket。这篇主要是介绍下SOCK_DGRAM方式的通信,即数据包的方式(与UDP类似),面向无连接。
这个代码是我刚开始学的时候写的,代码比较简单,适合初学,学习最快的方式就是直接拿源码修改、编译运行、调试。
完整源代码:零散Demo代码: 平时写的一些示例代码基本框架,封装,自定义控件等 - Gitee.com
创建服务端代码:
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; }
编译运行结果
左边是服务端,右边是客户端。
编辑