【问题标题】:Dealing with UDP unreliability处理 UDP 不可靠性
【发布时间】:2018-04-05 19:13:36
【问题描述】:

我在 Java 中使用 DatagramPacket 和 DatagramSocket 类通过 UDP 发送消息。我对网络的了解不完整。我知道:

  1. 当一个数据报被发送时,它实际上可能被分割成多个在网络上独立传播的数据(例如,如果我的数据报长度大于 MTU)。

  2. UDP 不保证消息在接收时的顺序(并且根本不保证消息的接收)。

将这些信息放在一起,我“理解”如果我发送一个(大)DatagramPacket,我可能会以任何顺序接收我的数据报的字节(甚至可能丢失某些部分)!但我想我误解了一些东西,因为如果是这样的话,没有人会使用这样的协议。

如何确保我收到的数据报(如果我收到的话)与我发送的数据报相同?

【问题讨论】:

  • 好问题。 UDP 用于流视频 (youtube) 或音乐之类的东西,这些东西并不重要。这是因为 UDP 不进行 3 次握手来确认数据到达那里,但正因为如此,UDP 更快。 TCP 则相反,它进行 3 次握手以确认数据到达那里。使用 UDP 通常如果数据包丢失,视频和音乐仍然可以播放(一些音频/视频延迟但仍然可以播放)。如果您想要一个示例,我创建了一个 TCP Web 服务器和一个 UDP 用于分配,请查看我的 Java 部分:katianie.com/blog/source-code
  • 感谢您的回答。但因此,我的问题是:如何确保接收到的 DatagramPacket 等于发送的 DatagramPacket?例如,如果我只制作小的 DatagramsPackets(不超过 MTU),我是否可以保证它们在旅行中不会被拆分?如果我有这个保证,我将知道我收到的 DatagramPackets 是一致的,我将能够将数据利用到其中。
  • 你需要做一些挖掘工作。您的问题的答案将来自对代码进行试验,将其与其他示例进行比较并阅读一些文档。

标签: java udp


【解决方案1】:

你的理解不正确。如果您的数据报在发送端被 IP(在 UDP 层以下)分解成片段,那么接收端的 IP 将按照正确的顺序重新组合这些片段,然后将整个重新组合的数据报传递到接收端的 UDP 层。如果数据报的任何片段丢失,则重组将失败,部分重构的数据报将被丢弃,并且不会向上传递到接收者的 UDP 层。因此,接收 UDP——以及接收应用程序——要么得到一个完整的数据报,要么什么也得不到。它永远不会得到部分数据报,也永远不会得到内容因碎片而被打乱的数据报。

如果传入的数据报大于应用程序的接收缓冲区,则可以为接收应用程序提供部分(截断的)数据报,但这与碎片无关。

【讨论】:

    【解决方案2】:

    将这些信息放在一起,我“理解”如果我发送一个(大)DatagramPacket,我可能会以任何顺序接收我的数据报的字节

    没有。

    (有些部分甚至可能会丢失)!

    没有。

    您将收到完整的 UDP 数据报或根本不接收。

    但我想我误解了一些东西,因为如果是这样的话,没有人会使用这样的协议。

    正确。事实并非如此。

    如何确保我收到的数据报(如果收到的话)与我发送的数据报相同?

    总是如此。 如果它到达。但是,它可能会到达零次、一次或多次,并且可能会乱序到达。

    普遍接受的最大实际 UDP 数据报大小是 534 字节的有效负载。您可以保证 IP 不会在发送方或任何中间主机上对其进行分段,并且不分段会降低您丢失数据包的机会。 (如@ottomeister 所述,如果任何片段丢失,则数据报也会丢失。)

    如果序列对您很重要,您的数据报中需要序列号。这也有助于防止出现重复,因为您知道要使用的序列号,因此您可以发现重复。

    如果到达对您很重要,您需要一个基于 ACK 或 NACK 的应用程序协议。

    【讨论】:

      猜你喜欢
      • 2017-05-10
      • 1970-01-01
      • 2013-04-01
      • 1970-01-01
      • 2012-05-06
      • 2011-09-25
      • 2011-03-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多