C ++:如何测量非阻塞套接字上的实际上传速率

时间:2013-07-26 10:28:02

标签: c++ linux sockets send nonblocking

我正在使用带有epoll的非阻塞套接字在linux C ++上编写程序,等待EPOLLOUT以便为某些数据执行send()。

我的问题是:我已经读过,在非阻塞模式下,数据被复制到内核的缓冲区,因此send()调用可能会立即返回,表明所有数据都已发送,实际上它只是复制到内核的缓冲区。

如何了解实际传输速率,我如何知道远程对等方实际发送和接收数据的时间?

4 个答案:

答案 0 :(得分:2)

您可以使用IOCTL获取内核套接字缓冲区中的当前数据量。这将允许您检查实际发送的内容。我不确定它有多重要,除非你有大量缓冲区和少量数据发送它可能不感兴趣。

调查插座fd上的TIOCOUTQ / TIOCINQ ioctl。

答案 1 :(得分:2)

  

我的问题是:我已经在非阻塞模式下读到数据被复制到内核的缓冲区

这种情况发生在所有模式中,而不仅仅是非阻塞模式。我建议你复习你的阅读材料。

  

因此send()调用可以立即返回,表明所有数据都已发送,实际上它只被复制到内核的缓冲区。

在所有模式中都是如此。

  

如何了解实际传输速率,我如何知道远程对等方实际发送和接收数据的时间?

当你发送了所有数据后,关闭套接字输出,然后设置阻塞模式和读取,或继续选择“可读”;然后在任何一种情况下都要读取应该产生的EOS。这可以作为关闭的同行确认。然后停止计时器。

答案 2 :(得分:2)

无论是否处于非阻塞模式,只要数据被复制到内核缓冲区,send就会返回。阻塞和非阻塞模式之间的区别在于缓冲区已满。在完整缓冲区的情况下,阻塞模式将挂起当前线程,直到写入发生,而非阻塞模式将立即返回EAGAIN或EWOULDBLOCK。

在TCP连接中,内核缓冲区通常等于窗口大小,因此只要有太多数据未被确认,连接就会阻塞。这意味着发送方知道远程端接收数据的速度有多快。

使用UDP它有点复杂,因为没有确认。这里只有接收端能够测量真实的速度,因为发送的数据可能在途中丢失。

在TCP和UDP情况下,内核都不会尝试发送链路层无法处理的数据。如果网络拥塞,链路层也可以流出数据。

回到您的情况,当使用非阻塞套接字时,您可以测量网络速度,前提是您正确处理EAGAIN或EWOULDBLOCK错误。对于发送比当前窗口大小(可能是64K左右)更多数据的TCP来说,这当然是正确的,您也可以通过UDP套接字了解链路层速度。

答案 3 :(得分:1)

send()只是将数据放入内核的缓冲区然后退出,让内核在后台执行实际的传输,所以你真正要做的就是测量内核接受你的传出数据的速度。除非对等体收到每个接收到的缓冲区的确认(并且无法检测何时收到TCP自己的确认),否则无法真正测量实际传输速度。但是,使用send()可以阻止太多数据仍然存在的事实可以帮助您弄清楚代码将传出数据传递给send()的事实。

send()告诉您接受了多少字节。因此,计算近似接受速度非常容易 - 将接受的字节数除以上一次调用后经过的时间量send()。因此,当您致电send()发送X字节并返回Y个字节时,请将时间记录为time1,再次致电send()以发送X返回} bytes并获取Y个字节,将时间记录为time2,您将看到您的代码以大约Y / ((time2-time1) in ms)字节/毫秒发送数据,然后您可以使用它来计算{根据需要{1}}。在数据传输的整个生命周期中,您可以非常了解应用程序的一般传输速度。