6

我有一个简单的客户端/服务器设置。服务器是 C 语言,而查询服务器的客户端是 Java。

我的问题是,当我通过连接发送带宽密集型数据(例如视频帧)时,它会丢弃多达一半的数据包。我确保在服务器端正确地对 udp 数据包进行分段(udp 的最大有效负载长度为 2^16)。我验证了服务器正在发送数据包(printf sendto() 的结果)。但是java似乎并没有得到一半的数据。

此外,当我切换到 TCP 时,所有视频帧都通过了,但延迟开始增加,在运行几秒钟后增加了几秒钟的延迟。

有什么明显的我失踪了吗?我似乎无法弄清楚这一点。

4

5 回答 5

9

获取一个像Wireshark这样的网络工具,这样你就可以看到网络上发生了什么。

UDP 不进行重传尝试,因此如果数据包在某处丢失,则由程序来处理丢失。TCP 将努力将所有数据包按顺序传递给程序,丢弃重复数据并自行请求丢失的数据包。如果您看到高延迟,我敢打赌您也会看到大量 TCP 数据包丢失,这将显示为来自服务器的重新传输。如果您没有看到 TCP 重新传输,则可能是客户端处理数据的速度不够快,无法跟上。

于 2010-03-14T02:04:18.387 回答
3

任何基于 UDP 的应用程序协议都不可避免地容易受到数据包丢失、重新排序和(在某些情况下)重复的影响。UDP 中的“U”可以代表“不可靠”,就像在不可靠数据报协议中一样。(好吧,它真的代表“用户”......但它肯定是记住 UDP 特性的好方法。)

UDP 数据包丢失通常是因为您的流量超出了服务器和客户端之间的一个或多个“跃点”的缓冲容量。发生这种情况时,数据包会被丢弃……由于您使用的是 UDP,因此没有传输协议级别的通知表明这种情况正在发生。

如果您在应用程序中使用 UDP,则应用程序需要考虑 UDP 的不可靠特性,实现自己的机制来处理丢弃和乱序的数据包并进行自己的流量控制。(一个应用程序在没有考虑到这可能对已经超载的网络产生影响的情况下爆出 UDP 数据包是一个糟糕的网络公民。)

(在 TCP 的情况下,数据包也可能被丢弃,但 TCP 正在检测并重新发送丢弃的数据包,并且 TCP 流控制机制正在启动以降低数据传输速率。最终结果是“延迟”。 )

编辑- 根据 OP 的评论,他的问题的原因是客户端没有“监听”一段时间,导致数据包(可能)被客户端的操作系统丢弃。解决这个问题的方法是:

  1. 使用一个专门的 Java 线程,它只读取数据包并将它们排队进行处理,并且

  2. 增加套接字的内核数据包队列的大小。

但即使您采取了这些措施,您仍然可能会丢弃数据包。例如,如果机器过载,应用程序可能无法获得足够频繁的执行时间片来读取和排队所有数据包,然后内核不得不丢弃它们。

编辑 2 - 关于 UDP 是否容易重复存在一些争论。毫无疑问,UDP 没有天生的重复检测或预防功能。但是,作为互联网的 IP 数据包路由结构也不太可能自发复制数据包。因此,如果确实发生了重复,则很可能会发生,因为发送方已决定重新发送 UDP 数据包。因此,在我看来,虽然 UDP 容易受到重复问题的影响,但它本身不会导致它们……除非操作系统协议堆栈或 IP 结构中存在错误。

于 2010-03-14T01:56:03.327 回答
2

尽管 UDP 支持长度最大为 65535 字节的数据包(包括8 字节的 UDP 标头 - 但请参见注释 1),但您和目标之间的底层传输不支持那么长的 IP 数据包。例如,以太网帧的最大大小为 1500 字节——考虑到 IP 和 UDP 报头的开销,这意味着任何数据有效载荷长度超过 1450 的 UDP 数据包都可能被分割成多个 IP 数据报。

最大大小的 UDP 数据包将被分成至少 45 个单独的 IP 数据报 - 如果这些片段中的任何一个丢失,则整个 UDP 数据包都会丢失。如果你的底层丢包率为 1%,你的应用会看到大约 36% 的丢包率!

如果您想看到更少的数据包丢失,请不要发送大数据包 - 将每个数据包中的数据限制在 1400 字节左右(或者甚至执行您自己的“路径 MTU 发现”来确定您可以安全发送而不会产生碎片的最大大小) .


  1. 当然,UDP也受到IP的限制,IP数据报的最大大小为65535,包括IP头。IP 标头的大小范围为 20 到 60 字节,因此在 UDP 数据包中可传输的最大应用程序数据量可能低至 65467。
于 2010-03-14T03:06:00.550 回答
0

问题可能与您的传输缓冲区在您的 UDPSocket 中被填满有关。一次只发送由 指示的字节数UDPSocket.getSendBufferSize()。用于setSendBufferSize(int size)增加此值。

如果#send() 用于发送大于 SO_SNDBUF 设置的 DatagramPacket,则发送或丢弃数据包是特定于实现的。

于 2010-03-14T02:41:07.043 回答
0

IP支持高达 65535 字节的数据包,包括20字节的 IP 数据包标头。UDP支持高达 65507 字节的数据报,加上 20 字节的 IP 报头和 8 字节的UDP头。但是网络 MTU 是实际限制,不要忘记它不仅包括这 28 个字节,还包括以太网帧头。未分段 UDP的真正实际限制是 576 字节的最小 MTU 减去所有开销。

于 2010-03-14T04:35:49.243 回答