<aside> 💡 本地套接字的作用:实现本地的进程间通信

</aside>

本地套接字通信的流程

服务器端

  1. 创建监听的套接字

    // AF_UNIX / AF_LOCAL 表示本地套接字通信
    int lfd = socket(AF_UNIX/AF_LOCAL, SOCK_STREAM, 0);
    
  2. 监听的套接字绑定本地的套接字文件 -> server端

    Untitled

    // 本地套接字socket地址——sockaddr_un
    // 头文件: sys/un.h
    #define UNIX_PATH_MAX 108
    
    struct sockaddr_un {
    		sa_family_t sun_family;         // 地址族协议,本地套接字指定 AF_LOCAL
    		char sun_path[UNIX_PATH_MAX];   // 套接字文件的路径, 这是一个伪文件, 大小永远=0
    																	  // 实际的读写操作都在内核的缓冲区中进行
    };
    
    // 绑定套接字
    struct sockaddr_un addr;
    // 绑定成功之后,addr的成员sun_path中的套接字文件会自动生成。
    bind(lfd, addr, len);
    
  3. 监听

    listen(lfd, 100);
    
  4. 等待并接受连接请求

    struct sockaddr_un cliaddr;
    int cfd = accept(lfd, &cliaddr, len);
    
  5. 通信

  6. 关闭连接

    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. 通信

  5. 关闭连接

    close();
    

示例代码

服务端

#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;
}