哪个是按顺序发送大型 UDP 数据包的最佳方法

Posted

技术标签:

【中文标题】哪个是按顺序发送大型 UDP 数据包的最佳方法【英文标题】:Which is the best approach to send large UDP packets in sequence 【发布时间】:2013-10-04 03:40:25 【问题描述】:

我有一个 android 应用程序需要每 100 毫秒通过协议 UDP 发送数据。每个 UDP 数据包平均有 15000 字节。数据包以广播方式发送

下面的每 100 毫秒行运行一个循环。

DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, broadcast, 9876); 
clientSocket.send(sendPacket);

应用程序开始正常工作,但大约 1 分钟后,接收数据包的频率会降低,直到数据包没有到达目的地。

UDP 数据包最大大小的理论限制(在 Windows 上)为 65507 字节

我知道网络的媒体 MTU 是 1500 字节,当我发送一个更大的数据包时,它会被分成几个片段,如果一个片段没有到达目的地,整个数据包就会丢失。

我不明白为什么在前 1 分钟数据包被正确发送,而在一段时间后数据包没有到达更多。所以我想知道解决这个问题的最佳方法是什么?

【问题讨论】:

BTW 片段也可能乱序到达。 ;) 我认为 TCP 不是一个选项? 我正在发送图片,如果我丢失了大约 30% 的数据包不会有问题。在这种情况下,tcp 速度较慢不是一个好主意。我的问题是一段时间后所有数据包都丢失了。谢谢 "我知道网络的媒体 MTU 是 1500 字节" - 很多网络都比这小。这只是以太网帧的大小。 ***.com/questions/47903/… 【参考方案1】:

这正是你描述的问题。您广播的每个数据报都被分成 44 个数据包。如果其中任何一个丢失,则数据报丢失。一旦你有足够的流量导致 1% 的数据包丢失,你就有 35% 的数据报丢失。 2% 的数据包丢失等于 60% 的数据报丢失。

您需要使您的广播数据报足够小,以免碎片化。如果您有一个 65,507 字节块的流,而您无法更改必须拥有整个块才能使数据有用的事实,那么天真的 UDP 广播是不好的选择。

我必须更多地了解您的应用程序的细节才能提出明智的建议。但是,如果您有一个大约 64KB 的数据块,这样您需要整个数据块才能使数据有用,并且您无法更改它,那么您应该使用一种方法将该数据分成具有一些冗余的片段,这样有些碎片可能会丢失。使用erasure coding,您可以将 65,507 字节的数据分成 46 个块,每块 1,490 字节,这样就可以从任意 44 个块中重构出原始数据。这将容忍适度的数据报丢失,数据大小仅增加约 4%。

【讨论】:

(致 OP)一个选项是将 UDP 消息拆分为几个更小的 UDP 消息,因此如果一个数据包丢失,只有一小部分数据丢失。当然,这意味着您可能需要一种机制来在接收方“重建”原始消息,这可能会要求重复丢失的数据报。在 UDP 上有效地实现(类似于)TCP。 我有一个 android 应用程序,它使用 opencv 分析来自相机的帧并通过 UDP 将这些帧发送到另一台设备。我将尝试压缩更多帧并划分为具有冗余的图表,并研究擦除代码。谢谢你的提示。我只是不明白为什么平均执行 1 分钟后包丢失更大。 你是在最大化带宽还是有足够的空间? TCP 遇到同样的性能问题,因为整个数据包都被丢弃,如果单个片段丢失,则必须重新发送。这是因为可靠性是在数据包级别而不是片段级别实现的。 然而 TCP 堆栈几乎总是尝试将消息拆分为小于 MTU 的数据包,从而避免碎片化。本质上是在 TCP 层将消息预分片成更小的数据包,这样如果单个小数据包丢失,TCP 层可以重新发送它并重建更大的消息。对于不可避免的大消息,TCP 可能比 UDP 执行得更好。【参考方案2】:

当您需要可靠且正确排序的交付时,专门使用 TCP 而不是 UDP。但假设您确实需要 UDP 进行广播,您可以:

    调试网络以查看数据包丢失的方式和位置,或者可能是接收器阻塞/滞后。但通常你无法控制这些事情。是否涉及 WiFi 网络?如果是这样,很难获得良好的 QoS。

    在应用层做一些事情来确保有序和可靠的交付。例如,SIP 通常使用 UDP,但该协议使用事务和序列号,因此客户端和服务器将根据需要重新传输消息。

    实现丢包隐藏。使用数学,接收器可以重新创建丢失的数据包,类似于 RAID 磁盘设置如何丢失驱动器并仍然运行。

您的设置可以正常工作一分钟,然后并不暗示广播或接收端存在网络拥塞或软件拥塞。

你能用 Wireshark 做一些数据包捕获并分享结果吗?

【讨论】:

我不知道 Wireshark。我会读到它。我没想过要在网络上进行调试。对我来说了解正在发生的事情并进一步了解它可能是一个好主意。感谢您的提示。 我只是选择了 UDP,因为我的应用程序要发送一系列图像,每个包一个图像,如果应用程序丢失了一些包,那也没有问题。我希望传输尽可能快,所以我选择了 UDP。数据通过使用 WIFI 的专用网络传输。

以上是关于哪个是按顺序发送大型 UDP 数据包的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

如果我在 C# 中发送 0 有效载荷数据,udp 数据包的大小是多少?

无法接收使用 GCDAsyncSocket 发送的 UDP 数据包的响应

确定哪个 IP 地址收到了数据包

从大型数据集中过滤掉记录的最佳方法是什么

黏包的原理 (tcp udp)

获取接收到的UDP数据包的目的地址