2

我正在使用 asio(非 boost 版本)库通过 10GB 以太网适配器捕获传入的 UDP 数据包。每秒 150k 个数据包很好,但是当我达到更高的速率(例如 300k 个数据包/秒)时,我开始丢弃数据包。

我很确定瓶颈在于 DMA 从网卡到主机系统的 300k 单独传输。传输并不大,每次传输只有 1400 字节,所以不是带宽问题。

理想情况下,我想要一种机制来将来自多个数据包的数据合并到一个到主机的单个 DMA 传输中。目前我正在使用 asio::receive 进行同步传输,它提供比 async_receive 更好的性能。

我曾尝试使用带有更大缓冲区的接收命令,或使用多个缓冲区的数组,但我似乎总是获得 1400 字节的单次读取。

有没有办法解决?

理想情况下,我想一次读取 1400 个字节的多个字节,只要填充总数不需要太长时间。IE。等待最多 4 毫秒,然后返回 4 x 1400 字节,或者只是在 4 毫秒后返回,但有多少字节可用......

我不控制整个网络,所以我不能强制使用巨型帧:(

干杯,

4

2 回答 2

3

我会移除该asio层并直接进入金属。

如果您在 Linux 上,您应该使用recvmmsg(2)而不是recvmsg()or recvfrom(),因为它至少允许在内核中一次传输多条消息,而其他消息则不允许。

如果你不能做这两件事,你至少需要缓和你的期望。recvfrom()并且recvmsg()任何覆盖它们的东西asio都不会一次传送超过一个 UDP 数据报。你需要:

  • 尽可能加快接收循环,消除所有可能的开销,尤其是动态内存分配和其他套接字或文件的 I/O。
  • 确保套接字接收器缓冲区尽可能大,至少一兆字节, via setsockopt()/SO_RCVBUFSIZ,并且不要假设您设置的就是您得到的:将其取回 viagetsockopt()以查看平台是否以某种方式限制了您。
于 2017-03-01T03:43:53.593 回答
1

可能您可以使用 libcap 库http://www.tcpdump.org/尝试使用 tcpdump 的解决方法并过滤以接收 UDP 数据包

于 2017-03-01T03:36:31.493 回答