我正在尝试确定机器接收数据包、处理数据包并返回答案所需的时间。
这台机器,我称之为“服务器”,运行一个非常简单的程序,它在缓冲区中接收数据包(recv(2)
),将接收到的内容(memcpy(3)
)复制到另一个缓冲区,然后将数据包发回(send(2)
)。服务器运行 NetBSD 5.1.2。
我的客户多次测量往返时间(pkt_count
):
struct timespec start, end;
for(i = 0; i < pkt_count; ++i)
{
printf("%d ", i+1);
clock_gettime(CLOCK_MONOTONIC, &start);
send(sock, send_buf, pkt_size, 0);
recv(sock, recv_buf, pkt_size, 0);
clock_gettime(CLOCK_MONOTONIC, &end);
//struct timespec nsleep = {.tv_sec = 0, .tv_nsec = 100000};
//nanosleep(&nsleep, NULL);
printf("%.3f ", timespec_diff_usec(&end, &start));
}
为了清楚起见,我删除了错误检查和其他小事。客户端在 Ubuntu 12.04 64 位上运行。这两个程序都以实时优先级运行,尽管只有 Ubuntu 内核是实时的 (-rt)。程序之间的连接是 TCP。这工作正常,平均给我 750 微秒。
但是,如果我启用注释掉的 nanosleep 调用(睡眠时间为 100 µs),我的测量值会下降 100 µs,平均为 650 µs。如果我睡了 200 µs,测量值会下降到 550 µs,依此类推。这一直持续到 600 µs 的睡眠,平均为 150 µs。然后,如果我将睡眠时间提高到 700 µs,我的测量值平均会上升到 800 µs。我用 Wireshark 确认了我的程序的措施。
我无法弄清楚发生了什么。我已经在客户端和服务器中设置了 TCP_NODELAY 套接字选项,没有区别。我使用了UDP,没有区别(相同的行为)。所以我猜这种行为不是由于 Nagle 算法。会是什么呢?
[更新]
这是客户端与 Wireshark 一起输出的屏幕截图。现在,我在另一台机器上运行我的服务器。我使用具有相同配置的相同操作系统(因为它是笔式驱动器中的 Live System),但硬件不同。这种行为没有出现,一切都按预期工作。但问题仍然存在:为什么它会发生在以前的硬件中?
[更新 2:更多信息]
正如我之前所说,我在两台不同的服务器计算机上测试了我的一对程序(客户端/服务器)。我绘制了获得的两个结果。
第一台服务器(奇怪的)是一台RTD 单板计算机,具有 1Gbps 以太网接口。第二台服务器(普通服务器)是具有 100Mbps 以太网接口的Diamond 单板计算机。他们都从相同的 pendrive 运行相同的操作系统 (NetBSD 5.1.2)。
从这些结果来看,我确实相信这种行为是由于驱动程序或网卡本身造成的,尽管我仍然无法想象为什么会发生这种情况......