任何基于 UDP 的应用程序协议都不可避免地容易受到数据包丢失、重新排序和(在某些情况下)重复的影响。UDP 中的“U”可以代表“不可靠”,就像在不可靠数据报协议中一样。(好吧,它真的代表“用户”......但它肯定是记住 UDP 特性的好方法。)
UDP 数据包丢失通常是因为您的流量超出了服务器和客户端之间的一个或多个“跃点”的缓冲容量。发生这种情况时,数据包会被丢弃……由于您使用的是 UDP,因此没有传输协议级别的通知表明这种情况正在发生。
如果您在应用程序中使用 UDP,则应用程序需要考虑 UDP 的不可靠特性,实现自己的机制来处理丢弃和乱序的数据包并进行自己的流量控制。(一个应用程序在没有考虑到这可能对已经超载的网络产生影响的情况下爆出 UDP 数据包是一个糟糕的网络公民。)
(在 TCP 的情况下,数据包也可能被丢弃,但 TCP 正在检测并重新发送丢弃的数据包,并且 TCP 流控制机制正在启动以降低数据传输速率。最终结果是“延迟”。 )
编辑- 根据 OP 的评论,他的问题的原因是客户端没有“监听”一段时间,导致数据包(可能)被客户端的操作系统丢弃。解决这个问题的方法是:
使用一个专门的 Java 线程,它只读取数据包并将它们排队进行处理,并且
增加套接字的内核数据包队列的大小。
但即使您采取了这些措施,您仍然可能会丢弃数据包。例如,如果机器过载,应用程序可能无法获得足够频繁的执行时间片来读取和排队所有数据包,然后内核不得不丢弃它们。
编辑 2 - 关于 UDP 是否容易重复存在一些争论。毫无疑问,UDP 没有天生的重复检测或预防功能。但是,作为互联网的 IP 数据包路由结构也不太可能自发复制数据包。因此,如果确实发生了重复,则很可能会发生,因为发送方已决定重新发送 UDP 数据包。因此,在我看来,虽然 UDP 容易受到重复问题的影响,但它本身不会导致它们……除非操作系统协议堆栈或 IP 结构中存在错误。