参考文章: [1]Unix Domain Socket– IPC通信机制 [2]How fast are Unix domain sockets? [3]read()函数参数理解
一、Unix域的Socket通信及其优点基于socket的框架上发展出一种IPC机制,就是UNIX Domain Socket。虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),但是UNIX Domain Socket用于IPC 更有效率及可靠 :
- 不需要经过网络协议栈
- 不需要打包拆包、计算校验和、维护序号和应答等,可靠性更强
- UNIX Domain Socket传输效率比通过loopback地址快将近一倍
- socket通信基本概念
- LINUX文件操作函数
对于知识一,已经在前面介绍过了。Linux文件操作函数用到了两个:read()和write()。简单介绍一下:
read - 从文件描述符里读取数据
#include ssize_t read(int fd, void *buf, size_t count);
fd:文件描述符,对于本文而言是socket套接字 buf:缓冲区指针 count:预期读取的字节数 返回值:表示实际读到的字节数(字符串结束符 '\0’不算)
write - 从文件描述符里写入数据
#include ssize_t read(int fd, void *buf, size_t count);
fd:文件描述符,对于本文而言是socket套接字 buf:缓冲区指针 count:预期写入的字节数 返回值:表示实际写入的字节数(字符串结束符 '\0’不算)
三、程序的功能及其实现程序的功能是实现客户端发送一个整型数据,服务端返回一个倒序的整型数据。
需要解决的问题:
- 创建服务端和客户端
- 数据处理
数据处理部分函数实现:
int num_reverse(int num) { int S=0,sum=0; while(num) { S=num%10; sum=10*sum+S; num = num / 10; } return sum; }
服务端函数:
#include #include #include #include #include #include #include //define the sockaddr_un structure int num_reverse(int num); int main() { /* 断开之前的socket文件 */ unlink("server_socket"); /* 创建一个socket */ int server_sockfd = socket(AF_UNIX, SOCK_STREAM, 0); struct sockaddr_un server_addr; server_addr.sun_family = AF_UNIX; strcpy(server_addr.sun_path, "server_socket"); /* 与本地文件进行绑定 */ bind(server_sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)); /* 监听 */ if(listen(server_sockfd, 5)<0); { perror("Listen failed"); } int client_sockfd; struct sockaddr_un client_addr; socklen_t len = sizeof(client_addr); while(1) { printf("server waiting:\n"); /* 接受一个客户端的链接 */ client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_addr, &len); /*数据交换 */ read(client_sockfd, &num, 4); printf("get an integer from client: %d\n", num); num=num_reverse(num); write(client_sockfd, &num, 4); /* 关闭socket */ close(client_sockfd); } return 0; } int num_reverse(int num) { int S=0,sum=0; while(num) { S=num%10; sum=10*sum+S; num = num / 10; } return sum; }
客户端:
#include #include #include #include #include #include #include int main() { /* 创建一个socket */ int sockfd = socket(AF_UNIX, SOCK_STREAM, 0); struct sockaddr_un address; address.sun_family = AF_UNIX; strcpy(address.sun_path, "server_socket"); /*从键盘读取需要转置的整数*/ int num; printf("Please enter the num to reverse:\n"); /* 链接至服务端 */ int result = connect(sockfd, (struct sockaddr *)&address, sizeof(address)); if(result == -1) { perror("connect failed: "); exit(1); } /* 数据处理 */ write(sockfd, &num, 4);//一个int 4个字节 read(sockfd, &num, 4); printf("get an integer from server: %d\n", num); /* 关闭socket */ close(sockfd); return 0; }
makefile:
all:server.c client.c gcc -g -Wall -o server server.c gcc -g -Wall -o client client.c clean: rm -rf *.o server client四、验证结果
启动server端:
启动client端: