做io测试

使用 send / recv 做 IO 性能测试(TCP)

send/recv 是 Linux socket 原生接口,适合做用户态TCP IO吞吐、延迟测试 ,区别于 epoll/io_uring,这里给最简单的阻塞版本,再给性能测试思路。 原理:服务端 recv,客户端 send,传输固定大小数据,统计耗时、带宽。

一、完整C代码(阻塞TCP,send/recv 测试)

server.c(接收端,recv)

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>

#define PORT 8888
#define BUF_SIZE (1<<20) // 1MB buffer

int main() {
    int server_fd, new_socket;
    struct sockaddr_in addr;
    socklen_t addrlen = sizeof(addr);
    char *buf = malloc(BUF_SIZE);

    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = htons(PORT);

    bind(server_fd, (struct sockaddr*)&addr, sizeof(addr));
    listen(server_fd, 1);
    printf("server listen on %d\n", PORT);

    new_socket = accept(server_fd, (struct sockaddr*)&addr, &addrlen);
    printf("client connected\n");

    long long total_recv = 0;
    clock_t start = clock();

    while (1) {
        int n = recv(new_socket, buf, BUF_SIZE, 0);
        if (n <= 0) break;
        total_recv += n;
    }

    clock_t end = clock();
    double sec = (double)(end - start)/CLOCKS_PER_SEC;
    printf("recv total: %lld bytes, time: %.2fs, bw: %.2f MB/s\n",
           total_recv, sec, total_recv / sec / (1<<20));

    close(new_socket);
    close(server_fd);
    free(buf);
    return 0;
}

client.c(发送端,send)

复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>

#define PORT 8888
#define BUF_SIZE (1<<20)
#define SEND_TOTAL (10LL << 30) // 10GB 测试流量

int main() {
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in serv_addr;
    char *buf = malloc(BUF_SIZE);
    memset(buf, 'A', BUF_SIZE);

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(PORT);
    inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);

    connect(sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
    printf("connected to server\n");

    long long remain = SEND_TOTAL;
    clock_t start = clock();

    while (remain > 0) {
        int send_len = (remain > BUF_SIZE) ? BUF_SIZE : remain;
        int n = send(sock, buf, send_len, 0);
        if (n <= 0) {
            perror("send");
            break;
        }
        remain -= n;
    }

    clock_t end = clock();
    double sec = (double)(end - start)/CLOCKS_PER_SEC;
    printf("send total: %lld bytes, time: %.2fs, bw: %.2f MB/s\n",
           SEND_TOTAL, sec, SEND_TOTAL / sec / (1<<20));

    close(sock);
    free(buf);
    return 0;
}

二、编译 & 运行

复制代码
gcc server.c -o server -O2
gcc client.c -o client -O2

窗口1(服务端)

复制代码
./server

窗口2(客户端)

复制代码
./client

默认本地回环测试 10GB 流量,测 TCP 吞吐。 改 127.0.0.1 换成远端IP,测跨机器网络IO。

三、send/recv 关键坑(做IO测试必须注意)

  1. send 不代表数据已经送到对端 send 只是拷贝到内核 socket send buffer,成功返回仅代表拷贝完成;真正收完是对端 recv。

    所以吞吐统计一定要以 server recv 累计字节为准,client send 的计数会偏乐观。

  2. send/recv 返回值永远要检查 TCP是字节流,不保证一次send多少就一次recv多少 。 send() 返回可能小于传入长度(部分发送),上面代码已经处理了剩余数据。

  3. buffer 大小影响测试结果 调整 BUF_SIZE:4k/64k/1M/4M,用来测试不同应用层缓冲区对IO的影响。

  4. 阻塞 vs 非阻塞 上面是阻塞socket。 非阻塞:fcntl(sock, F_SETFL, O_NONBLOCK),此时 send/recv 可能返回 -1,errno=EAGAIN,需要循环重试。适合高并发IO测试。

  5. socket buffer 调优(提升上限)

    临时修改内核tcp缓冲区

    sysctl -w net.core.rmem_max=16777216
    sysctl -w net.core.wmem_max=16777216

代码里也可以用 setsockopt 设置 SO_RCVBUF / SO_SNDBUF。

参考链接 :0voice · GitHub

相关推荐
一世繁华行16 分钟前
CAPL浏览器(翻译自官方文档)
运维·服务器·数据库
万联WANFLOW24 分钟前
让分散的设备像在同一张局域网里:企业组网技术解析
运维·网络·网络安全·智能路由器
q275513004237 分钟前
AS8132 DP转HDMI 4K60(420)被动式 国产性价比AS方案
linux·算法·硬件架构·dash
刚入门的大一新生1 小时前
Linux-进程间通信2
linux·运维·服务器
电科_银尘1 小时前
【深度学习项目实战·02】Linux服务器环境搭建:从SSH登录到稳定运行项目
linux·服务器·深度学习
QY_Research_1 小时前
全球智能交通系统物联网市场规模及CAGR14.2%深度分析
大数据·网络·人工智能·物联网·制造
梦帮科技1 小时前
量子纠缠网络与量子隐形传态攻防:量子中继器信道串扰、纠缠态保真度降解与量子路由劫持
开发语言·网络·人工智能·算法·自动化·php
开开心心就好2 小时前
发票信息录入太麻烦?离线工具一键转表格
运维·服务器·前端·pdf·ocr·maven·intellij-idea
运维小斌2 小时前
麒麟 V10 部署 OceanBase:故障速查与验收清单
linux·数据库·oceanbase·麒麟
水饺编程2 小时前
第2章:Linux 基础,在 root 中创建用户账号
linux·c语言·汇编·1024程序员节