【问题标题】:Is it possible to guarantee delivery of messages using UDP on Node.js?是否可以保证在 Node.js 上使用 UDP 传递消息?
【发布时间】:2013-03-26 04:21:05
【问题描述】:

如何保证在 Node.js 上使用 UDP 传递消息?例如,如果数据包失败,我可以重新发送数据包 - 但是有没有办法识别它何时失败?另外,丢包有多常见?

【问题讨论】:

  • @downvoter 需要解释一下吗?
  • 我认为没有理由拒绝投票......但知道 UDP 没有交付协议的一部分,谷歌搜索会发现这一点。我猜不赞成票是“你尝试了什么”的结果。
  • TCP 是处理错误的方法。
  • @j_mcnally 我知道 UDP 不能保证传递,我要问的是如何保证消息传递。我进行了编辑以使其更清晰。
  • 如果重要的是使用 TCP,那就是它的用途,这就像问有没有办法知道人们是否可以穿越黑洞。

标签: node.js udp


【解决方案1】:

如果您真正想知道的是“我如何检测丢失的数据包”?然后一般的技术是让接收者为每个发送的数据包发送一个确认。如果发送器没有收到确认,那么它必须重新发送数据包。如果接收方收到重复的数据包,那么它应该丢弃重复的数据包。

基本方案是这样的:

TX                               RX
 ╷           data
 ╰──────────────────────────────▶

              ack               ╷
 ◄──────────────────────────────╯

 ╷           data
 ╰────────────────────── - - -         loss of data packet
               .
               .
               . timeout
               .
 ╷       data retransmit
 ╰──────────────────────────────▶

              ack               ╷
 ◄──────────────────────────────╯

 ╷           data
 ╰──────────────────────────────▶

              ack               ╷
      - - - ────────────────────╯      loss of ack packet
               .
               . timeout
               .

 ╷       data retransmit
 ╰──────────────────────────────▶

              ack               ╷
 ◄──────────────────────────────╯

这本质上是所有形式的丢包检测的基础。可以实施一些改进来改进该技术,但基本原理大致相同:如果接收方没有告诉您数据包已到达,则数据包丢失。

通常对算法进行的第一个改进是检查 ack 是否真的是适当的 ack,而不仅仅是路由器发送的一些回声、信号交叉干扰或软件错误。解决方案是实现一个切换位。数据包在切换位设置为一个值的情况下传输,确认包需要以适当的值(通常是相同的值)回复。如果切换位错误,则表示 ack 数据包与最后一个数据包不匹配,这意味着它与前一个数据包匹配。这意味着最后一个数据包还没有被确认,这意味着出现了严重错误,应该重新传输数据包,直到收到正确的确认。

TX                               RX
 ╷           data[0]
 ╰──────────────────────────────▶

              ack[0]            ╷
 ◄──────────────────────────────╯

 ╷           data[1]
 ╰──────────────────────────────▶

              ack[0]            ╷
 ◄──────────────────────────────╯     ack mismatch!

 ╷       data[1] retransmit
 ╰──────────────────────────────▶

一些现实世界的协议使用这种技术,包括用于控制工业设备和机器人的大多数协议。

下一步实际上是对上述想法的扩展。与其发送一点,为什么不发送一个数字。这样,您可以更明确地将 ack 与数据包匹配,从而更准确地检测哪个数据包丢失并需要重新传输。这种技术通常被称为滑动窗口技术,因为在某些时候数字会滚动并滑回零。因此,在无法检测到数据包丢失之前,您可以传输的最大数据包数是滑动窗口大小。

滑动窗口技术的一大优势是您可以发送大量数据包而无需等待确认。这显着提高了吞吐量:

TX                             RX
 ╷           data[1]
 ╰──────────────────────────────▶
 ╷           data[2]
 ╰──────────────────────────────▶
 ╷           data[3]
 ╰──────────────────────────────▶


              ack[1]            ╷
 ◄──────────────────────────────╯
              ack[2]            ╷
 ◄──────────────────────────────╯

 ╷           data[4]
 ╰──────────────────────────────▶
 ╷           data[5]
 ╰──────────────────────────────▶

              ack[3]            ╷
 ◄──────────────────────────────╯
              ack[5]            ╷
 ◄──────────────────────────────╯     ack[4] missing!
               .
               . timeout
               .

 ╷       data[4] retransmit
 ╰──────────────────────────────▶

以上是对丢包检测基本技术的简短总结。如果您希望所有 UDP 数据包都到达目的地,这就是您需要实现的。

您应该知道 TCP 已经实现了这一点,因此如果您不想重新发明轮子,您应该真正使用 TCP。创建 UDP 是因为在某些情况下丢包是可以接受的(想想音频/视频流)。

【讨论】:

    【解决方案2】:

    来自维基百科

    UDP 适用于不需要或在应用程序中执行错误检查和纠正的目的,避免在网络接口级别进行此类处理的开销。对时间敏感的应用程序通常使用 UDP,因为丢弃数据包比等待延迟数据包更可取,这在实时系统中可能不是一个选项。 [2]如果在网络接口级别需要纠错功能,应用程序可以使用为此目的设计的传输控制协议 (TCP) 或流控制传输协议 (SCTP)。

    如果你关心的话,如果数据包/消息到达那里,基本上使用 TCP。否则,在应用程序级别使用 UDP 重新发明 TCP。

    【讨论】:

      【解决方案3】:

      不可能保证在任何平台上都能传送特定的 UDP 数据包,而不仅仅是 node.js。如果您要查找的是基于 UDP 的可靠传递机制,请查找 e-net 之类的内容或搜索可靠的 UDP。

      编辑:或使用 TCP。

      【讨论】:

      • 不是特定的 UDP 数据包,而是消息本身。我在问是否可以重新发送丢失的数据包,直到它成功到达? (编辑:哦,我会读一下 enet,谢谢!)
      【解决方案4】:

      UDP 是一种无法保证传送的协议。如果你想保证,你应该在UDP之上实现一些协议。

      【讨论】:

        猜你喜欢
        • 2016-08-06
        • 1970-01-01
        • 2017-10-11
        • 2017-06-28
        • 2016-11-18
        • 1970-01-01
        • 1970-01-01
        • 2018-09-05
        • 1970-01-01
        相关资源
        最近更新 更多