我有一个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分钟内数据包被正确发送,一段时间后数据包不再到达。所以我想知道解决这个问题的最佳方法是什么?
答案 0 :(得分:10)
这正是你所描述的问题。您广播的每个数据报分为44个数据包。如果其中任何一个丢失,数据报将丢失。只要有足够的流量导致1%的数据包丢失,就会有35%的数据报丢失。 2%的数据包丢失等于60%的数据报丢失。
您需要保持广播数据报足够小,不要碎片化。如果您有一个65,507字节块的流,这样您就无法改变必须拥有整个数据块以使数据有用的事实,那么天真的UDP广播就是错误的选择。
我必须更多地了解您的应用程序的细节,以提出合理的建议。但是如果你有大约64KB的数据,这样你需要整个数据块才能使数据变得有用,并且你无法改变它,那么你应该使用一种方法将这些数据分成具有一定冗余的碎片,以便有些碎片可能丢失。使用erasure coding,您可以将65,507个字节的数据分成46个块,每个块包含1,490个字节,这样原始数据就可以从任何44个块中重建。这可以容忍中等数据报丢失,数据大小仅增加约4%。
答案 1 :(得分:2)
当您需要可靠且正确订购的交付时,TCP将专门用于代替UDP。但假设您确实需要UDP进行广播,您可以:
调试网络以了解如何&数据包丢失的地方,或者可能是阻塞/滞后的接收器。但通常你无法掌控这些事情。是否涉及WiFi网络?如果是这样,很难获得良好的QoS。
在应用程序层执行某些操作以确保订购和可靠交付。例如,SIP通常使用UDP,但协议使用事务和序列号,因此客户端&服务器将根据需要重新发送消息。
实现丢包隐藏。使用数学,接收器可以重新创建丢失的数据包,类似于RAID磁盘设置如何丢失驱动器并仍然可以正常运行。
您的设置可以正常工作一分钟,然后不会暗示广播或接收方存在网络拥塞或软件拥塞。
你能用Wireshark做一些数据包捕获并分享结果吗?