我写了一个网络程序作为一个网络项目的一部分。该程序生成一组数据包(TCP用于使用berkely socket API进行通信),并将其发送到特定端口,并测量其返回的响应。程序运行得很好,但我想做一些后端计算,比如我的程序实际生成的数据速率。我试图做的是,我测量了发送数据包的代码例程前后的时间,并将总数据除以该时间,即:
在一次例行程序中总共发送799个数据包,其中每个数据包为82字节,因此:
799 x 82 x 8=524144位。测量的时间=0.0001s,因此数据速率524144/0.0001=5.24gbps
这是我试过的代码:
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));
}
我想确认我是否正确地处理了这个问题。另外,如果这是正确的方法,是否有办法查明数据包实际以多大的速率从线中出来,即从以太网接口得到的数据包的实际物理速率?我们能估计一下我在程序中计算出的包速率(它处于用户模式,我希望它会慢得多,因为系统调用时要穿越用户/内核屏障)和实际包速率之间的差别吗?非常感谢大家的帮助。
谢谢。
最佳答案
我想这不是你想要的。你所拥有的将给你提供信息,但也许不是如何改进它的指标。
我通常担心的是测量套接字发送/接收关系中挂接的延迟。这通常涉及到测量在sends()之间花费的时间或以某种形式recv()等待的时间。
有几件事需要特别注意。您是依赖网络层来收集和缓冲发送的数据,还是仅在希望数据输出时才缓冲和执行发送?如果您通常希望关闭nagle缓冲(请参阅setsockopt和TCP_NODELAY),但请注意代码不会倒退。
接下来是缓冲。您可能正在测量数据到达套接字缓冲区所需的时间,这几乎是即时的。如果您现在使用响应包的ack/coordination进行流式处理,这将在很长一段时间内得到平均值。您可以使用setsockopt()和SO RCVBUF/SO SNDBUF处理缓冲。
我要再往前走一点。如果您正在测量代码而不是物理网络的性能,并且您正在尽可能大的块中发送和接收数据包,那么还有两件事我通常会检查。
有ACK类型的协议吗。代码是否基本上以模式发送/接收。如果是这样,那么延迟可能是最大的问题。有很多方法可以解决这个问题,从允许多个独立的挂起请求流,到实现sliding windows。主要的想法是不要阻碍数据的流动。
最后,如果要处理recv(),通常不希望阻塞recv,除非您真的只想处理每个线程/进程的一个套接字关系。旧的解决方案是select(),对于合理的可伸缩性来说,这仍然是可行的。对于更大规模的解决方案,您可以使用epoll(linux)、kevents(osx)或IOCP(windows)。这些允许您将更多的记帐和(有时)线程池移回操作系统。如果您的问题真的是关于我可以从这个NIC中抽取多少数据的话,这就是您想要的地方;但是除非您处理多个连接,否则很少有必要。
很抱歉,如果我错过了你真正的要求,但我试图掩盖共同的问题。
关于c - Linux下C语言中数据包生成速率的测量,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9557939/