我使用Java中的DatagramPacket和DatagramSocket类来发送带有UDP的消息。我对网络知识不完整。我知道:
发送数据报时,实际上可能会将其拆分为多个在网络上独立传输的数据(例如,如果我的数据报长度大于MTU)。
UDP不保证接收时的消息顺序(并且根本不保证接收消息)。
将这些信息放在一起,我就能理解"如果我发送一个(大)DatagramPacket,我可能会以任何顺序收到我的数据报的字节(有些部分甚至可能会丢失)!但我认为我误解了一些事情,因为如果是这样的话,没有人会使用这样的协议。
如何确保收到的数据报(如果收到的数据报)与我发送的数据报相同?
答案 0 :(得分:1)
您的理解不正确。如果您的数据报在发送端通过IP(在UDP层之下)被分成片段,则接收器处的IP将以正确的顺序重新组合这些片段,然后将整个重组数据报传递到接收器的UDP层。如果数据报的任何片段丢失,则重组将失败,部分重建的数据报将被丢弃,并且不会将任何内容传递到接收器的UDP层。因此,接收UDP - 以及接收应用程序 - 获得完整的数据报或什么都不是。它永远不会得到部分数据报,并且它永远不会得到一个数据报,其内容因碎片而被扰乱。
如果传入的数据报大于应用程序的接收缓冲区,则可以为接收应用程序提供部分(截断的)数据报,但这与碎片无关。
答案 1 :(得分:0)
将这些信息放在一起,我就能理解"如果我发送一个(大)DatagramPacket,我可以按任何顺序接收我的数据报的字节
没有
(有些部分甚至可能缺失)!
没有
您将完整地收到UDP数据报,或者根本不收到。
但我认为我误解了一些事情,因为如果是这样的话,没有人会使用这样的协议。
正确。事实并非如此。
如何确保收到的数据报(如果收到的数据报)与我发送的数据报相同?
一直都是。 如果它到了。但是它可能会到达零次,一次或多次,并且可能无序到达。
普遍接受的最大实际UDP数据报大小是534字节的有效载荷。您可以保证IP不会在发送方或任何中间主机上对IP进行分段,并且非分段会降低丢包的可能性。 (如果任何片段丢失,数据报将丢失,如@ottomeister所述。)
如果序列对您很重要,则需要数据报中的序列号。这也可以帮助保护您免受重复,因为您知道您要查找的序列号,以便发现重复。
如果到达对您很重要,则需要基于ACK或NACK的应用程序协议。