【问题标题】:Packet Generation rate measurement in C under LinuxLinux下C语言包生成率测量
【发布时间】:2023-03-17 05:26:01
【问题描述】:

作为网络项目的一部分,我编写了一个网络程序。该程序生成一堆数据包(TCP 用于使用 berkely 套接字 API 进行通信)并将其发送到特定端口并测量它返回的响应。该程序运行良好,但我想做一些后端计算,例如我的程序实际生成的数据速率。我试图做的是我测量了发送数据包的代码例程之前和之后的时间,并将总数据除以那个时间,即: 一次共发送了 799 个数据包,其中每个数据包为 82 字节,因此:

799 x 82 x 8 = 524144 位。测量的时间为 = 0.0001s 所以数据速率 524144 / 0.0001 = 5.24 Gbps

这是我尝试过的一段代码:

struct timeval start,end;

double diffTime (struct timeval* start, struct timeval* end)
{
  double start_sec = ((double) start->tv_sec) + (double) start->tv_usec / 1000000.00;
  double end_sec = ((double) end->tv_sec) + (double) end->tv_usec / 1000000.00;
  return (end_sec - start_sec);
}
while(1){
gettimeofday(&start, NULL);  // getting start time

*/ Call packet sending routine */

gettimeofday(&end, NULL);

printf("Time taken for sending out a batch is %f secs\n", diffTime(&start,&end)); 
}

我想确认我是否正确地解决了这个问题。此外,如果这是正确的方法,是否有办法找出数据包从线路中出来的实际速率,即来自以太网接口的数据包的实际物理速率?我们能否估计一下我在程序中计算的数据包速率(在用户模式下,我希望它在系统调用中遍历用户/内核屏障时会慢很多)和实际数据包速率之间的差异?非常感谢所有帮助。

谢谢。

【问题讨论】:

  • 我不确定 65K 数据包大小是否有理由从您获得的时间中得出任何结论。数据量非常小,基本上只测量连接的延迟,而不是带宽。
  • 这是有道理的。还有什么我可以尝试获得更现实的结果吗?
  • 是的,发送更多包含更多数据的数据包。还可以尝试首先测量创建数据包所需的实际时间,这也可能很有趣。
  • 好的,我可以做到。其他计算确实有意义吗?我的意思是计算费率的方法?
  • 每个 TCP/IP 数据包都会添加标头数据,具体取决于版本和选项。以太网添加了另一个标头和校验和,因此您的值仅包括 netto 数据。您可以为每个数据包使用 IP 选项时间戳,并让发送方和接收方在系统时间上有所同步,以便接收方知道速率。

标签: c linux network-programming packet timeval


【解决方案1】:

我怀疑这不是你想要的。您所拥有的将为您提供信息,但可能不是如何改进它的指标。

通常我担心的是测量套接字发送/接收关系中的挂接延迟。这通常涉及测量我在发送() 之间花费了多长时间,或者我在某种形式的 recv() 中等待了多长时间。

通常需要注意几件事。您是依靠网络层来收集和缓冲您的发送,还是仅在您希望数据发出时才缓冲和发送?如果是后者,您通常希望关闭 nagle 缓冲(请参阅 setsockopt 和 TCP_NODELAY) - 但请注意代码不会回归。

接下来是缓冲。您可能正在测量数据到达套接字缓冲所需的时间,这几乎是即时的。如果您正在使用响应数据包的 now ack/coordination 进行流式传输,这将在很长一段时间内平均正常。您可以使用 setsockopt() 和 SO_RCVBUF/SO_SNDBUF 来处理缓冲问题。

我会走得更远一点。如果您正在测量代码而不是物理网络的性能,并且您正在尽可能大的块中发送和接收数据包,那么我通常会检查另外两件事。

  1. 您是否有 ACK 类型的协议。代码是否基本上以某种模式发送/接收。如果是这样,那么延迟可能是最大的问题。有很多方法可以解决这个问题,从允许多个挂起的请求独立返回,到实现sliding windows。主要思想是不要阻碍数据流。

  2. 最后,如果您正在处理 recv(),您通常不想阻塞在 recv 中,除非您真的只想处理每个线程/进程的一个套接字关系。老派的解决方案是 select(),这对于合理的可扩展性来说仍然是可行的。对于更大规模的解决方案,您可以使用 epoll(linux)、kevents(osx) 或 IOCP(windows)。这些允许您将更多的簿记和(有时)线程池移回操作系统。如果您的问题真的是关于我可以从这个 NIC 中抽取多少数据,那么这就是您想要的地方;但除非您处理多个连接,否则很少需要。

抱歉,如果我错过了您真正要问的内容,但我试图涵盖常见问题。

【讨论】:

  • 感谢乔指出这些事情。我试图照顾其中的一些。我使用 poll() 因为我的程序中模拟了多个执行异步 I/O 多路复用的客户端。所有的调用也是非阻塞的。我一直在测量数据速率部分并且没有任何经验,所以我尝试了这个。在较长时间内平均意味着我应该发送大量数据包并计算平均时间?
  • 我肯定会在您处于“稳定状态”之后查看一段时间内的性能。至少,您可能还想跟踪最慢、最快的,是的……甚至可能是标准偏差,以便您了解网络的可预测性。 (en.wikipedia.org/wiki/Algorithms_for_calculating_variance)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-29
  • 1970-01-01
  • 2012-12-02
  • 1970-01-01
  • 2021-12-16
相关资源
最近更新 更多