node.js - 是否可以保证在 Node.js 上使用 UDP 传递消息?

标签 node.js udp

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

最佳答案

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

基本方案是这样的:

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 包需要以适当的值(通常是相同的值)进行回复。如果切换位错误,则意味着 ack 数据包与最后一个数据包不匹配,这意味着它与前一个数据包匹配。这意味着最后一个数据包还没有被确认,这意味着出现了严重的错误,应该重新传输数据包,直到收到正确的确认。

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

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

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

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

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

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

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

滑动窗口技术的一大优点是你可以发送大量的数据包而不用等待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 的创建是因为在某些情况下数据包丢失是可以接受的(想想音频/视频流)。

关于node.js - 是否可以保证在 Node.js 上使用 UDP 传递消息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15629329/

相关文章:

javascript - Express.js 找不到样式表

node.js - sequelize node js中回调是怎么写的?

c++ - 如何用单个信号处理程序解决这个多个Linux计时器

c++ - Boost::asio udp socket - 我应该如何使用 API 来允许取消读取?

c - 具有多个客户端的 UDP 客户端服务器

node.js - 在 Node.js 中测试方法签名

mysql - 从所有记录中查找匹配的问题

node.js - NodeJS - 回调错误

networking - UDP 客户端 - 打开端口?

c - 从 sockaddr_storage 中提取 IP 地址和端口信息