我正在使用非阻塞套接字与epoll在Linux C ++编写一个程序,等待EPOLLOUT为了做一些数据发送()。
我的问题是:我读过非阻塞模式的数据复制到内核的缓冲区,因此一个send()调用可能会立即返回,表明所有的数据已发送,实际上它只被复制到内核的缓冲区。
如何知道数据实际发送和接收的时间,以了解真正的传输速率?
无论是否处于非阻塞模式,只要数据被复制到内核缓冲区,发送将立即返回。 阻塞和非阻塞模式的区别在于缓冲区已满。 在完整的缓冲区情况下,阻塞模式将挂起当前线程直到写入发生,而非阻塞模式将立即返回EAGAIN或EWOULDBLOCK。
在TCP连接中,内核缓冲区通常等于窗口大小,所以一旦有太多数据未被确认,连接就会被阻塞。 这意味着发送者知道远端接收数据的速度有多快。
对于UDP,它有点复杂,因为没有确认。 这里只有接收端能够测量真实的速度,因为发送的数据可能在途中丢失。
在TCP和UDP情况下,内核都不会尝试发送链路层无法处理的数据。 如果网络拥塞,链路层也会流出数据。
回到您的案例,使用非阻塞套接字时,您可以测量网络速度,只要您正确处理EAGAIN或EWOULDBLOCK错误。 对于发送比当前窗口大小(可能是64K左右)更多的数据的TCP,这当然是正确的,你也可以通过UDP套接字了解链路层速度。
您可以使用IOCTL获取内核套接字缓冲区中的当前数据量。 这将允许您检查实际发送的内容。 我不确定这个问题,但除非你有大量的缓冲区和少量的数据发送它可能不感兴趣。
调查你的socket fd上的TIOCOUTQ / TIOCINQ ioctl。
我的问题是:我读过非阻塞模式的数据被复制到内核的缓冲区
这发生在所有模式中,而不仅仅是非阻塞模式。 我建议你阅读你的阅读材料。
因此一个send()调用可能立即返回,表明所有的数据已经被发送,实际上它只被复制到内核的缓冲区中。
这在所有模式中都是如此。
我怎么知道数据实际发送和接收的远程对端,知道真正的传输速率?
当你发送了所有的数据,关闭套接字输出,然后设置阻塞模式并阅读,或者继续选择'可读'; 然后在这两种情况下阅读应该导致的EOS。 这起到了同行的密切关注。 然后停止计时器。
send()
只是将数据放入内核的缓冲区,然后退出,让内核在后台执行实际的传输,所以你只能测量内核接受外发数据的速度。 你不能真正的测量实际的传输速度,除非对方发送一个接收到的每个缓冲区的确认(并且没有办法检测何时收到了TCP自己的确认)。 但是,使用send()
可以阻塞太多数据仍然在飞行中的事实可以帮助您找出代码将传出数据传递给send()
真实情况。
send()
告诉你有多少字节被接受。 因此,计算近似的接受速度非常简单 – 将接受的字节数除以前一次调用send()
以来所经过的时间量。 所以当你调用send()
来发送X
字节并返回Y
字节时,记录时间为time1
,再次调用send()
来发送X
字节并返回Y
字节,记录时间为time2
,你会看到你的代码Y / ((time2-time1) in ms)
为单位大致以Y / ((time2-time1) in ms)
字节发送数据,然后根据需要使用该数据计算B/KB/MB/GB per ms/sec/min/hr
。 在数据传输的整个生命周期中,您可以很好地了解应用程序的一般传输速度。