我编写了一个网络程序,作为网络项目的一部分。该程序生成一组数据包(TCP用于使用berkely-socket API进行通信),并将其发送到特定端口,并测量其返回的响应。这个程序运行得很好,但我想做一些后端计算,比如我的程序实际生成的数据速率。我试图做的是,我测量了发送数据包的代码例程前后的时间,并将总数据除以时间I-e:一次程序总共发送799个数据包,其中每个数据包为82字节,因此:
799 x 82 x 8=524144位。测量的时间=0.0001s,因此数据速率524144/00.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 secsn", diffTime(&start,&end));
}
我想确认一下我处理这个问题是否正确。此外,如果这是正确的方法,有没有办法找出数据包从电线中流出的实际速率,即数据包从以太网接口的实际物理速率?我们能估计我在程序中计算的数据包速率(处于用户模式,我预计随着系统调用跨越用户/内核屏障,它会慢得多)和实际数据包速率之间的差异吗?非常感谢所有的帮助。
谢谢。
我怀疑这不是你想要的。你所拥有的会给你信息,但可能不是如何改进的指标。
通常,我担心的是测量套接字发送/接收关系中挂接的延迟。这通常包括测量我在sends()之间花费的时间,或者在某种形式的recv()中等待的时间。
通常有几件事需要注意。您是依靠网络层来收集和缓冲您的发送,还是仅在希望数据传出时才进行缓冲和发送?如果是后者,你通常想关闭nagle缓冲(请参阅setsockopt和TCP_NODELAY),但要小心,代码不会倒退。
接下来是缓冲。您可能正在测量数据到达套接字缓冲区所需的时间,这几乎是即时的。如果您现在使用响应数据包的ack/coordination进行流式传输,那么在很长一段时间内,这将是平均的。您可以使用setsockopt()和SO_RCVBUF/SO_SNDBUF处理缓冲。
我要去更远一点的地方。如果你测量的是代码而不是物理网络的性能,并且你在尽可能大的块中发送和接收数据包,我通常会检查另外两件事。
-
你有ACK类型的协议吗。代码基本上是以模式发送/recv吗。如果是这样的话,那么延迟可能是最大的问题。有很多方法可以解决这个问题,从允许多个独立返回的挂起请求,到实现滑动窗口。主要思想是不要阻碍数据的流动。
-
最后,如果您正在处理recv(),您通常不想在recv中阻塞,除非您真的只想处理每个线程/进程的一个套接字关系。旧的解决方案是select(),对于合理的可扩展性来说,这仍然是可行的。对于更大规模的解决方案,您可以选择epoll(linux)、kevents(osx)或IOCP(windows)。这允许您将更多的记账和(有时)线程池移回操作系统。如果你的问题真的是关于我可以从这个NIC中抽取多少数据,那么这就是你想要的;但除非您正在处理多个连接,否则很少是必要的。
如果我错过了你真正想要的,我很抱歉,但我试图涵盖常见的问题。