如何最小化UDP数据包丢失。

5

我每秒接收大约3000个UDP数据包,每个数据包的大小约为200字节。我编写了一个Java应用程序来监听这些UDP数据包,并将数据写入文件。然后服务器以预先指定的速率发送15000条消息。将数据写入文件后,其中仅包含大约3500条消息。使用Wireshark我确认了我的网络接口已经接收到了所有15000条消息。之后我尝试更改套接字的缓冲区大小(最初为8496字节):

(java.net.MulticastSocket)socket.setReceiveBufferSize(32*1024);

那个改变使得保存的信息数量增加到了大约8000个。我一直将缓冲区大小增加到1MB,之后,保存的信息数量达到了大约14400个。增加缓冲区大小到更大的值不会增加保存的信息数量。我认为我已经达到了所允许的最大缓冲区大小。但是,我仍然需要捕获由我的网络接口收到的所有15000条信息。
非常感谢您的帮助。

1
我不会使用UDP来获取文件,因为有文件损坏的风险,为什么不用TCP呢? - TeaCupApp
也许文件写入是瓶颈所在。 你尝试使用更大的缓冲区大小来使用BufferedOutputStream(OutputStream out, int size)了吗? - SKi
Brogrammer TCP不是组播网络的选项。 - tialaramex
5个回答

5

看起来像是一个bug,很可能是你的代码问题。如果UDP数据包通过网络传递,它们将被排队等待本地传递,就像在Wireshark中看到的那样。也许你的程序没有及时从其套接字读取数据 - 是否有专门的线程来执行此任务?

您可以通过检测您的程序丢失了哪些数据包来取得一些进展。如果所有丢失的数据包都是早期的,也许数据被发送在程序等待接收它们之前。如果它们全部在后面丢失,也许程序退出得太快了。如果它们以规则间隔出现,则可能存在循环接收数据包的代码问题等。

无论如何,您似乎对丢失的数据包异常担忧。按设计,UDP不是可靠的传输方式。如果这些多播数据包的丢失对您的系统造成问题(而不仅仅是因为性能原因想要解决这个谜团),那么系统设计就是错误的。


是的,有专门的线程来处理这个任务。而且我已经丢失了所有后来的消息。根据您的解释,我应该能够捕获到发送到我的网络接口的所有消息,对吗? - nath
1
这完全取决于你的平台。在Windows上,如果网络堆栈缓冲区已满,它将丢弃UDP数据报(因为它被允许这样做),所以你会看到你正在经历的情况(wireshark显示它们都到达了NIC,但你的程序没有收到所有数据,因为堆栈发现接收缓冲区已满并且丢弃了一些数据)。你可以使用SIO_ENABLE_CIRCULAR_QUEUEING ioctl来调整它的丢弃方式,请参见http://msdn.microsoft.com/en-us/library/windows/desktop/ms741621(v=vs.85).aspx - 总之,尽快读取数据报。 - Len Holgate

1
你遇到的问题似乎是写入文件时出现了延迟。我建议在将数据写入文件之前,把所有的数据读入内存中(或者使用另一个线程来写入文件)。
然而,使用UDP无法保证100%接收到所有数据包而没有能力要求再次发送数据包(这是TCP自动完成的)。

1
这听起来像是正确的解决方案。基本上,如果您想要比套接字库允许的更大的缓冲区,您将不得不在读取网络线程和写入磁盘线程之间,在您自己的应用程序中创建缓冲区。 - caf

1

我看到你正在使用UDP发送文件内容。在UDP中,数据包的顺序不能保证。如果您不担心顺序问题,可以将所有数据包放入队列中,并使用另一个线程处理队列并将内容写入文件。这样,套接字读取线程就不会因为文件操作而被阻塞。


0

这是一个仅适用于Windows的解决方案,但在网络控制器卡属性中进行以下更改可以显著减少我们使用情况下的数据包丢失率。

我们正在消耗大约200 Mbps的UDP数据,并在中等服务器负载下遇到了大量数据包丢失的问题。

所使用的网络卡是一张Asus ROG Aerion 10G卡,但我预计大多数高端网络控制器卡都会暴露类似的属性。您可以通过设备管理器->网络卡->右键单击->属性->高级选项来访问它们。

1. 增加接收缓冲区数量:

默认值为512;我们可以将其增加到1024。在我们的情况下,更高的设置被接受,但一旦超过1024,网络卡就会被禁用。在网络卡级别拥有更多可用缓冲区的数量可以使系统对从网络卡缓冲区传输数据到套接字缓冲区的延迟具有更高的容忍度,最终我们的应用程序可以读取数据。

2. 将中断调节速率设置为“关闭”:

如果我理解正确,中断调节将多个“缓冲区填充”通知(通过中断)合并为单个通知。因此,CPU 将不会经常被中断并在每次中断时获取多个缓冲区。这减少了 CPU 使用率,但增加了准备好的缓冲区被覆盖的机会,在延迟服务中断的情况下。

此外,我们增加了套接字缓冲区大小(与 OP 已经完成的相同),并且还在套接字级别启用了循环缓冲,如Len Holgate在评论中建议的那样,这应该也增加了处理套接字缓冲区的延迟容忍度。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接