【问题标题】:Which options is the best for send/receive packet in AF UNIX?哪些选项最适合在 AF UNIX 中发送/接收数据包?
【发布时间】:2021-08-16 15:11:18
【问题描述】:

在 AF_UNIX 套接字连接中,我必须从服务器发送/接收数据包,这些选项中的哪一个是最佳解决方案,为什么? 谢谢!

客户端主

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

#include <pthread.h>

#include <unistd.h>
#include <fcntl.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#define UNIX_PATH_MAX 108 
#define SOCKNAME "../../mysock"

// used only in option 3
typedef struct Packet {
    int id;
    int length;
    char *message;
} Packet;

int main(void) {
    int fd_skt, fd_c;
    char buf[N];
    struct sockaddr_un sa;
    strncpy(sa.sun_path, SOCKNAME, UNIX_PATH_MAX);
    sa.sun_family = AF_UNIX;

    fd_skt = socket(AF_UNIX,SOCK_STREAM,0);

    while (connect(fd_skt, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
        if (errno == ENOENT) {
            printf("NONE!");
            sleep(1);
        } else
            exit(EXIT_FAILURE);
    }

    int id = 3;
    char message[6] = "hello"; // h e l l o \0
    int length = strlen(message) + 1;

选项 1:使用 3 种不同的写入方式发送数据包

    /**
     * Send the packet with 3 different write
     */

    write(fd_skt, &id, sizeof(int));
    write(fd_skt, &length, sizeof(int));
    write(fd_skt, message, length);

    sleep(5);
    read(fd_skt, buf, N);
    printf("Client got : %s\n", buf);
    close(fd_skt);

    return 0;
}

方案2:创建缓冲区,使用memcpy将数据放入缓冲区,先将缓冲区大小发送给服务器,再发送整个数据包

    /**
     * Create a buffer, using memcpy to put data in the buffer, send first the buffer size to the server, and after the whole packet
     */

    int size = strlen(message) + 1 + sizeof(int) + sizeof(int);
    void *buffer = malloc(sizeof(size));

    memcpy(buffer, &id, sizeof(int));
    memcpy(buffer + 4, &length, sizeof(int));
    memcpy(buffer + 8, message, length);

    write(fd_skt, &size, sizeof(int));
    write(fd_skt, buffer, size);

    sleep(5);
    read(fd_skt, buf, N);
    printf("Client got : %s\n", buf);
    close(fd_skt);

    return 0;
}

选项3:使用结构创建数据包(服务器具有相同的结构),首先将数据包大小发送到服务器,然后在发送结构后,将其转换为 (void *) &packet

    /**
     * Create the packet using a struct (the server has the same struct), send first the packet size to the server and after send the struct, casting it as (void *) &packet
     */

    int size = strlen(message) + 1 + sizeof(int) + sizeof(int);

    Packet packet;
    packet.id = id;
    packet.length = length;
    packet.message = "hello";

    write(fd_skt, &size, sizeof(int));
    write(fd_skt, (void *) &packet, size);

    sleep(5);
    read(fd_skt, buf, N);
    printf("Client got : %s\n", buf);
    close(fd_skt);

    return 0;
}

【问题讨论】:

    标签: c sockets networking serialization struct


    【解决方案1】:

    每种方法之间没有真正的不同。选择使您的程序更具可读性的那个。性能主要取决于实现。

    拥有一个write() 将确保使用线路上最少数量的数据包发送数据,如果线路上的数据质量非常好,这是最快的传输方式。

    【讨论】:

    • IIRC 即使多次调用write(),如果它们在一定时间内,流也可能决定只使用一个数据包..
    • @thebusybee 是的,这就是为什么有一个选项 TCP_NODELAY 和所谓的 Nagle 算法
    猜你喜欢
    • 1970-01-01
    • 2020-05-23
    • 2023-03-03
    • 2020-09-03
    • 1970-01-01
    • 2012-10-03
    • 2012-05-20
    • 2011-05-30
    • 1970-01-01
    相关资源
    最近更新 更多