You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何TCP Socket往返时延低于Linux网络栈时延?

网络时延测量异常问题

我搭建了一套实验环境:两台机器通过以太网直连,均配备10Gbps网卡(IXGBE驱动),且处于同一网络可互相ping通。我用一套用户态-内核态网络栈时延测量代码得到的结果约为100微秒,但自己编写的TCP Socket客户端/服务端在直连时的往返时延(Round Trip Time,RTT)居然低于这个数值,对此我感到困惑。

服务端代码(server.c)

#define PORT            8080
#define BUFFER_SIZE     1024
#define PACKET_SIZE     1024

int main() {
    int     socket_fd, new_socket, rc;

    // 创建套接字文件描述符
    socket_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_fd  == 0) {
        perror("Socket creation error");
        exit(EXIT_FAILURE);
    }


    // 设置套接字选项
    int opt = 1;
    rc = setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
    if (rc < 0) {
        perror("Setsockopt failed");
        exit(EXIT_FAILURE);
    }

    // 绑定地址与端口
    struct sockaddr_in address;
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = INADDR_ANY;
    address.sin_port = htons(PORT);

    rc = bind(socket_fd, (struct sockaddr *)&address, sizeof(address));
    if (rc < 0) {
        perror("Socket bind failed");
        exit(1);
    }

    printf("Listening to %s:%d\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port));
    if (listen(socket_fd, 3)) {
        perror("Listen failed");
        exit(EXIT_FAILURE);
    }

    // 接受连接
    int addrlen = sizeof(address);
    new_socket = accept(socket_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen);
    if (new_socket < 0) {
        perror("Accept failure");
        exit(EXIT_FAILURE);
    }

    // 打印客户端地址
    char ip_address[INET_ADDRSTRLEN];
    inet_ntop(AF_INET, &(address.sin_addr), ip_address, INET_ADDRSTRLEN);
    printf("New connection from %s:%d\n", ip_address, ntohs(address.sin_port));
    
    // 循环接收并回复数据
    int val_read, val_send;
    char    buff[BUFFER_SIZE];
    while (1) {
        memset(buff, 0, sizeof(buff));
        val_read = read(new_socket, buff, sizeof(buff));
        if(val_read == -1) {
            perror("Read failed");
            exit(EXIT_FAILURE);
        }
        else if (val_read > 0) {
            val_send = send(new_socket, buff, sizeof(buff), 0);
            if (val_send == -1) {
                perror("Send failed");
                exit(EXIT_FAILURE);
            }
        }
    }
    close(socket_fd);
    return 0;
}

客户端代码(client.c)

#define PORT            8080
#define NUM_MESSAGES    1024
#define ROLLING_COUNT   32
#define PACKET_SIZE     32
#define BUFFER_SIZE     1024
#define DEST_ADDRESS    "192.168.10.223"

int main() {
    int sock = 0;
    int total_latency = 0;

    struct sockaddr_in serv_addr;
    struct in_addr dest_addr; 
    memset(&dest_addr, 0, sizeof(struct in_addr));
    inet_pton(AF_INET, DEST_ADDRESS, &dest_addr);


    serv_addr.sin_addr = dest_addr;
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);


    // 打印目标信息
    printf("Destination address is %s\n", inet_ntoa(dest_addr));
    printf("Destination port    is %d\n", PORT);
    
    // 创建套接字
    sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0) {
        perror("Socket creation error");
        exit(EXIT_FAILURE);
    }

    // 连接服务端
    int c = connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    if (c < 0) {
        perror("Connection failed");
        exit(EXIT_FAILURE);
    }
    printf("Connected to server!\n");


    // 定义时间变量与缓冲区
    struct timeval start_time, end_time;
    char message[PACKET_SIZE] = {};
    char buffer[BUFFER_SIZE] = {};

    memset(message, 'A', strlen(message));
    double latency;

    // 开始发送并接收数据
    printf("Ready to send/recv messages\n");

    for (int i = 0; i < NUM_MESSAGES; i++) {
        gettimeofday(&start_time, NULL);

        if (send(sock, message, sizeof(message), 0) == -1) {
            perror("Send failed");
            continue;
        }

        if (recv(sock, buffer, sizeof(buffer), SO_RCVTIMEO) == -1) {
            perror("Recv failed");
            continue;
        }

        gettimeofday(&end_time, NULL);
        latency = (end_time.tv_sec - start_time.tv_sec) * 1000000 + 
                  (end_time.tv_usec - start_time.tv_usec);
        printf("%d Message sent at %d.%06d, recv at %d.%06d, latency %06d\n", 
            i, start_time.tv_sec, start_time.tv_usec, end_time.tv_sec, end_time.tv_usec, (int)latency);
    }
    printf("Finished!");
    close(sock);
    return 0;
}

异常现象与疑问

我测量的时延是客户端发送消息到收到回复的时间差:

  • 使用连接共享网络的eth0接口时,往返时延约900-1000微秒,结果合理;
  • 但使用直连以太网的接口时,往返时延低于80微秒,这让我无法理解。

另外还有一个奇怪的现象:启动客户端/服务端后,ping的时延会显著降低,关闭服务端后ping时延恢复正常,这是为什么?

内容的提问来源于stack exchange,提问作者akastack

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 18:18:08