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_local
    char 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

猜你喜欢

转载自blog.csdn.net/Alkaid2000/article/details/130042529