ubuntu实现unix domain socket通信
来源:互联网 发布:动漫小说软件 编辑:程序博客网 时间:2024/05/28 05:18
socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIX Domain Socket。虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是UNIX Domain Socket用于IPC更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。
UNIX Domain Socket是全双工的,API接口语义丰富,相比其它IPC机制有明显的优越性,目前已成为使用最广泛的IPC机制,比如X Window服务器和GUI程序之间就是通过UNIX Domain Socket通讯的。
使用UNIX Domain Socket的过程和网络socket十分相似,也要先调用socket()创建一个socket文件描述符,address family指定为AF_UNIX,type可以选择SOCK_DGRAM或SOCK_STREAM,protocol参数仍然指定为0即可。
unix domain的socket通信和网络socket不同的地方在于地址格式不同,用结构体sockaddr_un表示,网络编程的socket地址是IP地址加端口号,而UNIX Domain Socket的地址是一个socket类型的文件在文件系统中的路径,这个socket文件由bind()调用创建,如果调用bind()时该文件已存在,则bind()错误返回。
接下来是server端代码和client代码:
/****************** server program *****************/#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <stdlib.h>#include <sys/un.h>int main(){ int sockfd,newfd,ret,recv_num,recv_num_total=0; char buf[50]; struct sockaddr_un server_addr; remove("/myfiles/test/server.socket");/*不管有没有,先删除一下,否则如果该文件已经存在的的话,bind会失败。*/ memset(&server_addr,0,sizeof(server_addr)); server_addr.sun_family=AF_UNIX; strcpy(server_addr.sun_path,"/myfiles/test/server.socket"); sockfd=socket(AF_UNIX,SOCK_STREAM,0); if (sockfd<0) { printf("调用socket函数建立socket描述符出错!\n"); exit(1); } printf("调用socket函数建立socket描述符成功!\n"); ret=bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(server_addr)); if (ret<0) { printf("调用bind函数绑定套接字与地址出错!\n"); exit(2); } printf("调用bind函数绑定套接字与地址成功!\n"); ret=listen(sockfd,4); if (ret<0) { printf("调用listen函数出错,无法宣告服务器已经可以接受连接!\n"); exit(3); } printf("调用listen函数成功,宣告服务器已经可以接受连接请求!\n"); newfd=accept(sockfd,NULL,NULL);/*newfd连接到调用connect的客户端*/ if (newfd<0) { printf("调用accept函数出错,无法接受连接请求,建立连接失败!\n"); exit(4); } printf("调用accept函数成功,服务器与客户端建立连接成功!\n"); while (1) { recv_num=recv(newfd,buf,24,0); if (recv_num<0) printf("调用recv接受失败!\n"); else { recv_num_total+=recv_num; printf("调用recv函数成功,本次接受到%d个字节,内容为:\"%s\"。共受到%d个字节的数据。\n",recv_num,buf,recv_num_total); } sleep(2); }}
/****************** client program *****************/#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <string.h>#include <stdlib.h>#include <sys/un.h>int main(){ int sockfd,ret,send_num,send_num_total=0; char buf[]="this is my socket data."; struct sockaddr_un server_addr; memset(&server_addr,0,sizeof(server_addr)); server_addr.sun_family=AF_UNIX; strcpy(server_addr.sun_path,"/myfiles/test/server.socket"); sockfd=socket(AF_UNIX,SOCK_STREAM,0); if (sockfd<0) { printf("调用socket函数建立socket描述符出错!\n"); exit(1); } printf("调用socket函数建立socket描述符成功!\n"); ret=connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(server_addr)); if (ret<0) { printf("调用connect函数失败,客户端连接服务器失败!\n "); exit(2); } printf("调用connect函数成功,客户端连接服务器成功!\n"); while (1) { send_num=send(sockfd,buf,sizeof(buf),MSG_DONTWAIT); if (send_num<0) printf("调用send函数失败!"); else { send_num_total+=send_num; printf("调用send函数成功,本次发送%d个字节,内容为:\"%s\"。目前共发送了%d个字节的数据。\n",send_num,buf,send_num_total); } sleep(2); }}
两个程序通过gcc编译完成后,运行server时,出现了一个问题:
查看程序发现,这里调用bind函数需要创建一个socket文件,因此需要对目录有写的权限,利用ls命令查看目录发现目录只有读和执行的权限,
因此利用chmod更改目录权限:sudo chmod -R 777 /myfiles/test
改后重新执行程序,成功运行server端程序
接着打开一个新的终端,运行client程序,两者通信成功
在这里发现代码有一些bug,比如当终止client服务时,server端还是会显示,调用recv函数成功。如下所示
查看recv函数的用法可以发现:
当应用程序调用recv函数时,
(1)recv先等待s的发送缓冲中的数据被协议传送完毕,如果协议在传送s的发送缓冲中的数据时出现网络错误,那么recv函数返回SOCKET_ERROR,
(2)如果s的发送缓冲中没有数据或者数据被协议成功发送完毕后,recv先检查套接字s的接收缓冲区,如果s接收缓冲区中没有数据或者协议正在接收数据,那么recv就一直等待,直到协议把数据接收完毕。当协议把数据接收完毕,recv函数就把s的接收缓冲中的数据copy到buf中(注意协议接收到的数据可能大于buf的长度,所以 在这种情况下要调用几次recv函数才能把s的接收缓冲中的数据copy完。recv函数仅仅是copy数据,真正的接收数据是协议来完成的),
recv函数返回其实际copy的字节数。如果recv在copy时出错,那么它返回SOCKET_ERROR;如果recv函数在等待协议接收数据时网络中断了,那么它返回0。
上述情况属于网络中断,recv返回的是0。因此只要加上一个判断,当recv返回的数据是0时,则显示网络断开即可。
- ubuntu实现unix domain socket通信
- IPC通信之UNIX Domain Socket
- 进程间通信之 Unix Domain Socket
- 【转】UNIX环境domain socket通信方式
- Unix Domain Socket– IPC通信机制
- Unix Domain Socket – IPC通信机制
- 使用socket实现进程间通信:(UNIX domain中面向连接通信)
- Unix Domain Socket 域套接字实现
- Unix Domain Socket 域套接字实现
- /LGC设计模式/进程间通信之 Unix Domain Socket
- unix domain socket 进程间通信简析
- Unix domain socket
- UNIX Domain Socket IPC
- UNIX Domain Socket IPC
- Unix Domain Socket IPc
- UNIX Domain Socket IPC
- UNIX Domain Socket IPC
- unix domain socket
- 电路设计_继电器的电磁干扰
- Django中的request.GET和request.POST
- redis提示Could not get a resource from the pool(jedis连接池配置)
- APUE - POSIX Threads
- 如何让《算法》(第4版)的BinarySearch跑起来
- ubuntu实现unix domain socket通信
- linux学习之计算机基础(五)
- CCF——消除类游戏
- 编程珠玑:第二章 啊哈,算法三个问题
- 设计模式之简单工厂模式
- ++a和a++到底有什么区别?
- 【待解决】【360笔试】需要知识点总结
- qt qtabbar qss
- Service