Linux网络编程(五)——本地套接字通讯
目录
0x01 本地套接字实现流程
0x02 程序实现
客户端代码实现
服务端代码实现
0x01 本地套接字实现流程
对于之前学习的TCP/IP、UDP协议等,这些都是网络套接字通信,它同样也可以实现进程间的通信,只不过是面向不同主机的进程间的通信,其实就是网络通信,但是本地套接字是用于本地的进程间的通信,其可以实现:
-
有关系的进程间的通信。
-
没有关系的进程间的通信。
本地套接字实现流程和网络套接字类似,一般使用TCP进行通信,其流程主要如下:
对于服务端:
-
创建监听套接字
int lfd = socket(AF_UNIX/AF_LOCAL, SOCK_STREAM, 0);
// 使用结构体
#include <sys/un.h>
#define UNIX_PATH_MAX 108
struct sockaddr_un {sa_family_t sun_family; // 地址族协议 af_localchar sun_path[UNIX_PATH_MAX];
};
struct sockaddr_un addr; // 绑定成功之后,指定的sun_path中的套接字文件会自动生成。 bind(lfd, addr, len);
-
监听
listen(lfd,100);
-
等待并接受连接请求
struct sockaddr_un cliaddr; int cfd = accept(lfd, &cliaddr, len);
-
通信
接收数据:read/recv
发送数据:write/send
-
关闭连接:close()
对于客户端:
创建通信的套接字 int fd = socket(AF_UNIX/AF_LOCAL, SOCK_STREAM, 0);
监听的套接字绑定本地的IP 端口 struct sockaddr_un addr; // 绑定成功之后,指定的sun_path中的套接字文件会自动生成。 bind(lfd, addr, len);
连接服务器 struct sockaddr_un serveraddr; connect(fd, &serveraddr, sizeof(serveraddr));
通信 接收数据:read/recv 发送数据:write/send
关闭连接 close();
0x02 程序实现
客户端代码实现
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/un.h>int main() {unlink("client.sock");// 1.创建套接字int cfd = socket(AF_LOCAL, SOCK_STREAM, 0);if(cfd == -1) {perror("socket");exit(-1);}// 2.绑定本地套接字文件struct sockaddr_un addr;addr.sun_family = AF_LOCAL;strcpy(addr.sun_path, "client.sock");int ret = bind(cfd, (struct sockaddr *)&addr, sizeof(addr));if(ret == -1) {perror("bind");exit(-1);}// 3.连接服务器struct sockaddr_un seraddr;seraddr.sun_family = AF_LOCAL;strcpy(seraddr.sun_path, "server.sock");ret = connect(cfd, (struct sockaddr *)&seraddr, sizeof(seraddr));if(ret == -1) {perror("connect");exit(-1);}// 4.通信int num = 0;while(1) {// 发送数据char buf[128];sprintf(buf, "hello, i am client %d\\n", num++);send(cfd, buf, strlen(buf) + 1, 0);printf("client say : %s\\n", buf);// 接收数据int len = recv(cfd, buf, sizeof(buf), 0);if(len == -1) {perror("recv");exit(-1);} else if(len == 0) {printf("server closed....\\n");break;} else if(len > 0) {printf("server say : %s\\n", buf);}sleep(1);}close(cfd);return 0;
}
服务端代码实现
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/un.h>int main() {//在运行前删除某个文件unlink("server.sock");// 1.创建监听的套接字int lfd = socket(AF_LOCAL, SOCK_STREAM, 0);if(lfd == -1) {perror("socket");exit(-1);}// 2.绑定本地套接字文件struct sockaddr_un addr;addr.sun_family = AF_LOCAL;strcpy(addr.sun_path, "server.sock");//绑定成功会生成对应文件在目录下int ret = bind(lfd, (struct sockaddr *)&addr, sizeof(addr));if(ret == -1) {perror("bind");exit(-1);}// 3.监听ret = listen(lfd, 100);if(ret == -1) {perror("listen");exit(-1);}// 4.等待客户端连接struct sockaddr_un cliaddr;int len = sizeof(cliaddr);int cfd = accept(lfd, (struct sockaddr *)&cliaddr, &len);if(cfd == -1) {perror("accept");exit(-1);}printf("client socket filename: %s\\n", cliaddr.sun_path);// 5.通信while(1) {char buf[128];int len = recv(cfd, buf, sizeof(buf), 0);if(len == -1) {perror("recv");exit(-1);} else if(len == 0) {printf("client closed....\\n");break;} else if(len > 0) {printf("client say : %s\\n", buf);send(cfd, buf, len, 0);}}close(cfd);close(lfd);return 0;
}
可以理解为他们的通信其实就是绑定对应的文件,如果遇到关闭服务端、客户端时,又想绑定却遇到服务端、客户端在被占用的情况,这个时候可以将目录下的.sock
文件删除,也可以在程序前对文件进行删除,使用函数unlink
。