如何最小化UDP数据包丢失

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

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

该更改将保存的消息数量增加到~8000。 我不断将缓冲区大小增加到1MB。 之后,保存的消息数达到~14400。 将缓冲区大小增加到更大的值不会增加保存的消息数。 我想我已达到允许的最大缓冲区大小。 不过,我需要捕获网络接口收到的所有15000条消息。

任何帮助,将不胜感激。 提前致谢。

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

您可以通过检测程序丢失哪些数据包来取得一些进展。 如果丢失的所有数据包都是早期数据包,则可能是在程序等待接收数据之前发送数据。 如果他们都晚了,也许它会很快退出。 如果它们是固定间隔,则代码中可能会出现一些问题,这些问题会导致接收数据包。 等等

在任何情况下,你似乎都非常担心丢失的数据包。 根据设计,UDP不是可靠的传输方式。 如果丢失这些多播数据包对您的系统来说是一个问题(而不仅仅是出于性能原因而想要解决的一个谜),那么系统设计是错误的。

您似乎遇到的问题是您延迟写入文件。 我会在写入文件之前将所有数据读入内存(或者在另一个线程中写入文件)

但是,没有办法确保使用UDP接收100%的数据包而无法再次请求数据包(TCP为您提供的function)

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

接收缓冲区大小在OS级别配置。

例如,在Linux系统上, sysctl -w net.core.rmem_max=26214400如本文https://access.redhat.com/site/documentation/en-US/JBoss_Enterprise_Web_Platform/5/html/Administration_And_Configuration_Guide/jgroups-perf- udpbuffer.html