c++ - 以高数据包速率最小化丢弃的 UDP 数据包 (Windows 10)

标签 c++ sockets networking udp winsock

重要提示:我知道 UDP 是一个不可靠的协议(protocol)。但是,由于我不是提供数据的设备的制造商,我只能尽量减少影响。因此,请不要再发表任何关于 UDP 不可靠的声明。我需要建议将损失降至最低。

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

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

该软件同时处理所有摄像头,每个摄像头的流接收器被实现为一个单独的线程,并拥有自己的接收 UDP 套接字。
在一定的帧速率下,软件似乎每隔几分钟就会丢失一些 UDP 帧(即使网络容量仅使用了约 60-70%)。

硬件细节

  • 相机是国外厂商的!它们通过以太网将 UDP 流发送到可配置的 UDP 端点。不支持 TCP...
  • 摄像机通过自己的专用网络接口(interface) (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 毫秒超时以允许线程对全局关闭信号作出 react )。如果接收到一个数据包,它将存储在缓冲区中,并且循环立即继续接收任何进一步的数据包。

    问题

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

    最佳答案

    要提高 Widnows 上 GigE 相机的 UDP Rx 性能,您可能需要考虑编写自定义过滤器驱动程序 (NDIS)。这允许您拦截内核中的消息,阻止它们到达用户空间,将它们打包到某个缓冲区中,然后通过自定义 ioctl 发送到用户空间到您的应用程序。我已经做到了,大约花了一周的时间才完成。 Microsoft 提供了一个示例,我将其用作它的基础。
    也可以使用现有的通用驱动程序,例如 pcap,我也尝试过,大约花了半周时间。这不太好,因为 pcap 无法确定帧何时结束,因此数据包分组将是次优的。
    我建议首先深入研究网络堆栈设置,并确保 PC 不会缺乏资源。查看调整指南,例如用于此类负载的英特尔网卡可能比自定义驱动程序产生更大的影响。
    (我知道这是一个较旧的线程,你可能已经解决了你的问题。但是这样的事情对于 future 的冒险者来说是很好的记录......)

    关于c++ - 以高数据包速率最小化丢弃的 UDP 数据包 (Windows 10),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57789856/

    相关文章:

    c++ - 正确计算PTS和DTS同步音视频ffmpeg C++

    c++ - 为什么在尝试分配 4D 数组时会出现段错误(核心已转储)?

    c - 数据结构 union sockunion 只适用于 FreeBSD 还是也适用于 Linux?

    authentication - 发送客户端证书如何不将客户端暴露给模拟

    java - 重置 TCP 连接一侧

    c++ - C++初学者(计算和输出分数)

    c++ - 为什么迭代一个 vector 这么慢?

    javascript - 为 Web 应用程序实现 pub/sub 模式

    c - 如何使用 poll() 检测超时的客户端?

    networking - 浏览器 KB/s 是每秒 1000 字节还是 1024 字节?