在高数据包速率下最大限度地减少丢弃的 UDP 数据包 (Windows 10)

Minimizing dropped UDP packets at high packet rates (Windows 10)

本文关键字:数据包 UDP Windows 速率 最大限度      更新时间:2023-10-16

重要说明:我知道UDP是一种不可靠的协议。但是,由于我不是提供数据的设备的制造商,因此我只能尝试将影响降至最低。因此,请不要再发布任何关于UDP不可靠的声明。我需要建议将损失降至最低。

我已经实现了一个应用程序C++它需要在短时间内接收大量UDP数据包,并且需要在Windows(Winsock(下工作。该程序可以工作,但如果每个 UDP 流的数据速率(或数据包速率(达到一定水平,似乎会丢弃数据包......请注意,我无法将相机接口更改为使用 TCP。

详细信息:它是千兆以太网摄像机的客户端,它使用UDP数据包将其图像发送到计算机。每个摄像机的数据速率通常接近网络接口的容量(~每秒 120 兆字节(,这意味着即使使用 8KB 巨型帧,每个摄像机的数据包速率也为 10'000 到 15'000。目前我们已经将 4 台摄像机连接到一台计算机...这意味着每秒高达 60'000 个数据包。

该软件同时处理所有摄像机,并且每个摄像机的流接收器作为单独的线程实现,并具有自己的接收UDP套接字。 在一定的帧速率下,软件似乎每隔几分钟就会错过几个UDP帧(甚至网络容量也只被~60-70%使用(。

硬件详细信息

  • 相机来自国外制造商!它们通过以太网将 UDP 流发送到可配置的 UDP 端点。没有TCP支持...
  • 摄像机通过其自己的专用网络接口 (1GBit/s( 连接
  • 直接连接,不使用开关(!
  • 电缆为 CAT6e 或 CAT7

实施详细信息

到目前为止,我将SO_RCVBUF设置为一个较大的值:

int32_t rbufsize = 4100 * 3100 * 2; // two 12 MP images
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&rbufsize, sizeof(rbufsize)) == -1) {
perror("SO_RCVBUF");
throw runtime_error("Could not set socket option SO_RCVBUF.");
}

不会引发错误。因此,我假设该值已被接受。 我还使用以下代码将主进程的优先级设置为 HIGH-PRIORITY_CLASS:

SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); 

但是,我没有发现任何更改线程优先级的可能性。线程是在设置进程优先级后创建的...

接收方线程使用阻塞 IO 一次接收一个数据包(超时时间为 1000 毫秒,以允许线程对全局关闭信号做出反应(。如果收到数据包,它将存储在缓冲区中,循环会立即继续接收任何其他数据包。

问题

还有其他方法可以降低数据包丢失的可能性吗?是否有可能通过一次调用接收存储在套接字缓冲区中的所有数据包?(我不需要任何关于发送方的信息;只需要包含的有效载荷( 也许,您还可以建议一些注册表/网卡设置来检查...

若要提高 Widnows 上 GigE 相机的 UDP Rx 性能,可能需要考虑编写自定义筛选器驱动程序 (NDIS(。这允许您拦截内核中的消息,阻止它们到达用户空间,将它们打包到某个缓冲区中,然后通过自定义 ioctl 发送到您的应用程序的用户空间。我已经完成了这项工作,花了大约一周的时间才完成。Microsoft有一个示例可用,我将其用作它的基础。

也可以使用现有的通用驱动程序,例如 pcap,我也尝试过,花了大约半周的时间。这不太好,因为 pcap 无法确定帧何时结束,因此数据包分组将是次优的。

我建议首先深入挖掘网络堆栈设置,并确保PC不会缺乏资源。查看调整指南,例如针对此类负载的英特尔网卡,这可能会比自定义驱动程序产生更大的影响。

(我知道这是一个较旧的线程,您可能已经解决了您的问题。但像这样的事情对于未来的冒险家来说是很好的记录。

  • IOCP 和 WSARecv 在重叠模式下,您可以在 ~60k WSARecv 周围设置
  • 在处理 GetQueuedCompletionStatus 的线程上处理数据,并在该线程中执行 WSARecv 以在接收数据时使用的线程进行通信

请注意,您的UDP数据包大小应保持在MTU以下,这将导致丢弃,具体取决于摄像机和软件之间的所有网络硬件

  • 编写一些 UDP 测试器来模拟相机以测试网络,以确保硬件支持负载。

https://www.winsocketdotnetworkprogramming.com/winsock2programming/winsock2advancediomethod5e.html

WSArecvfrom for UDP 对 Windows 中的进程优先级敏感吗? 如果不是至少"高于正常"的过程优先级,我可以想象我会下降吗?