> 文章列表 > Linux网络编程(五)——本地套接字通讯

Linux网络编程(五)——本地套接字通讯

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()

对于客户端:

  1. 创建通信的套接字 int fd = socket(AF_UNIX/AF_LOCAL, SOCK_STREAM, 0);

  2. 监听的套接字绑定本地的IP 端口 struct sockaddr_un addr; // 绑定成功之后,指定的sun_path中的套接字文件会自动生成。 bind(lfd, addr, len);

  3. 连接服务器 struct sockaddr_un serveraddr; connect(fd, &serveraddr, sizeof(serveraddr));

  4. 通信 接收数据:read/recv 发送数据:write/send

  5. 关闭连接 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