操作 Windows 资源管理器窗口时 UDP 数据包丢失

Posted

技术标签:

【中文标题】操作 Windows 资源管理器窗口时 UDP 数据包丢失【英文标题】:UDP packet drops when manipulating Windows explorer window 【发布时间】:2017-04-19 10:13:50 【问题描述】:

我正在开发一个应用程序,接收高达 900 Mb/s 的数据,通过 UDP(1036 字节数据报大小)传入。在“正常”情况下(没有系统负载和用户交互),一切正常:操作系统和我的应用程序都没有报告丢失的数据报。当我开始单击 Windows 资源管理器的文件夹树,更改其主显示窗格的内容时,数据报被删除。我通过使用 Windows 性能监视器并检查数据报有效负载中烘焙的序列号来观察这一点。 这会导致每次点击都会丢失数百个数据报。

接收器缓冲区大小增加(128 MB 操作系统,甚至更多用于我的应用程序)。我进一步观察到没有缓冲区达到其限制,如果调用

ioctlsocket(my_socket, FIONREAD, &readableBytes);

返回准确的字节数。最高观察值低于 2 MB。 我不确定哪些其他缓冲区可能溢出以及如何跟踪它们的状态。

该应用程序是使用 Qt 开发的。除了 UDP 接收线程之外,还使用了其他三个线程。当没有用户交互并且接收线程被切断时,它们都是空闲的。所有这些都是重现问题的每个测试设置的情况。

接收线程的第一次迭代使用了一个 Qt UDP 套接字,并检查了正确的序列号。

第二次迭代使用普通的 WinSock 调用 recv(...),并在另一个线程中检查序列号。这显然增加了线程的数量。两个线程都通过无锁队列进行通信,该队列完全能够处理呈现给它的读取和写入操作。然而,即使只有接收线程在运行(读取数据报并丢弃它们),也可能会观察到与上述相同的行为。

即使是具有多个接收器线程(也只有读取和丢弃)的实现也会显示相同的行为。

即使数据速率降至 330 Mb/s,也可能会出现此问题,但频率会降低。它会在更低的数据速率下消失。

是的,我知道 UDP 不保证传送,但数据包显然到达了我的机器,并在有充足的 CPU 时间和可用缓冲区空间的情况下被丢弃 - 至少可以这么说,这似乎很奇怪。

我想知道的:

    这种行为有什么解释吗? 如果是这样,可能的解决方案是什么? 如果不是,可以通过什么检查来找出导致此问题的原因?

任何帮助或指导将不胜感激,谢谢!

【问题讨论】:

【参考方案1】:

简单的解释是您严重落后于传入的流。当你有 1kb 的数据包时,2MB 的缓冲数据是巨大的! UDP 旨在为您提供当前数据,而不是陈旧数据,并且当您的实时数据包落后 2000 个数据包时,网络堆栈会执行应有的操作并开始丢弃数据包。这是完全可以预料的。您可能应该有几十个数据包,在最坏的情况下,不是数千个。

您必须重写代码以使用分布在多个高优先级线程上的现代重叠 I/O,最好使用由网络堆栈直接填充的非复制数据包缓冲区。

Qt 在将其抽象化方面可以做得更好,但在有人实现它之前,您能做的最好的事情就是阅读有关 Windows 上的现代高性能网络并自己完成工作。

【讨论】:

UDP 可用于任何数据,而不仅仅是当前数据。例如,torrent 协议使用它进行传输,根据定义,它没有 当前数据 我使用“当前”可能是循环使用的意思是与最近到达的数据包相差不远的数据包。假设数据包以固定速率到达。如果是这样,接收缓冲区的填充显然是由于接收代码无法应对数据速率。保留这些数据包没有意义,队列只会增长,因此必须丢弃它们。 2MB 是千兆链路上约 22 毫秒的数据。 感谢您的回答!我假设您的意思是在重叠 I/O 模式下使用 WSARecv。

以上是关于操作 Windows 资源管理器窗口时 UDP 数据包丢失的主要内容,如果未能解决你的问题,请参考以下文章

windoes任务管理器中的“句柄数”是啥意思!

如何在Windows资源管理器右键菜单中 添加CMD

tcp和udp

用vs2010制作了c#windows窗体程序,但打包时在解决方案资源管理器窗口中找不到解决方案无

进程数多少正常

可选择和可拖动的 jQuery 以创建类似 Windows 资源管理器的窗口