我正在开发一个接收高达900 Mb / s数据的应用程序,通过UDP(1036字节数据报大小)进入。在“正常”情况下(没有系统加载和没有用户交互),一切正常:操作系统和我的应用程序都没有报告丢弃的数据报。当我开始单击Windows资源管理器的文件夹树,更改其主显示窗格的内容时,将删除数据报。我通过使用Windows性能监视器并检查数据报的有效负载中烘焙的序列号来观察到这一点。 这使得每次点击都会丢失数百个数据报。
接收器缓冲区大小增加(128 MB OS,甚至更多用于我的应用程序)。我进一步观察到,如果调用
,没有缓冲区达到其极限ioctlsocket(my_socket, FIONREAD, &readableBytes);
返回准确的字节数。最高观察值低于2 MB。 我不确定哪些其他缓冲区可能会溢出以及如何跟踪它们的状态。
使用Qt开发应用程序。除UDP接收线程外,还有三个其他线程在使用。当没有用户交互并且接收线程被切断时,所有这些都是空闲的。所有这些都是每个重现问题的测试设置的情况。
接收线程的第一次迭代使用了Qt UDP套接字,并检查了正确的序列号。
第二次迭代使用普通的WinSock调用recv(...),检查在另一个线程中完成的序列号。这显然增加了线程数量。两个线程都通过无锁队列进行通信,该队列完全能够处理呈现给它的读写操作。然而,即使只有接收器线程正在运行(读取数据报并丢弃它们),也可能会出现与上述相同的行为。
即使是具有多个接收器线程(也只是读取和丢弃)的实现,也会显示相同的行为。
即使数据速率降至330 Mb / s,也可能会出现问题,但随后频率降低。它以更低的数据速率消失。
是的我知道UDP不能保证传送,但是数据包显然已经到达我的机器并且在有足够的CPU时间和缓冲空间的情况下被丢弃 - 至少可以说这看起来很奇怪。
我想知道的事情:
任何帮助或指示都将不胜感激,谢谢!
答案 0 :(得分:2)
简单的解释是你在传入的流后面严重滞后。当你拥有1kb数据包时,2MB的缓冲数据巨大! UDP旨在为您提供当前数据,而不是过时数据,当您实时发送2000个数据包时,网络堆栈会执行应有的操作并开始丢弃数据包。这完全是预期的。你应该在你面前有几十个包,在最坏的情况下,不是数千个。
您必须重写代码才能使用分布在多个高优先级线程中的现代重叠I / O,理想情况下使用由网络堆栈直接填充的无副本数据包缓冲区。
Qt可以更好地抽象出来,但是直到有人实现它,你能做的最好的事情就是在Windows上阅读现代高性能网络并自己完成工作。