【问题标题】:How to detect that UDP packet has been lost? (C#)如何检测UDP数据包丢失? (C#)
【发布时间】:2023-03-30 06:51:02
【问题描述】:

我正在开发 SNTP 客户端,它通过 UDP 从 NTP 服务器获取时间戳。一切正常,我可以下载时间戳和更新 Windows 时钟,但如果 UDP 数据包丢失,我想收到一条消息。如何检测数据包何时丢失?我需要这些信息,因为如果数据丢失,我想获得新的时间戳。

...我该如何测试该功能?如何故意丢失UDP数据包?

【问题讨论】:

  • UDP 是单向的,您无法检测到数据包是否丢失。这是 TCP 和 UDP 的主要区别。
  • 这项服务究竟是如何工作的?您的客户端是否向服务器发出请求并等待响应,然后更新它的时间?或者您的客户端是否等待并侦听来自服务器的 UDP 数据包?无论哪种方式,您都无法真正验证 UDP 数据包的传输。根据您的需要,设置超时可能对您来说是一个更好的选择?如果在最后 X 秒内未更新时间或类似情况,则显示警告或引发异常或其他情况?

标签: c# udpclient ntp


【解决方案1】:

您有三个选择:

  1. 忽略丢弃的数据包
  2. 改用 TCP
  3. 构建您自己的检测系统

你问的是如何做#3,答案是:

  • 为每个数据包添加数据包编号和数据包时间戳。
  • 创建一个数据包堆栈并将传入的数据包插入到按数据包编号排序的堆栈中。
  • 仅当存在包号为(最后一个包号 + 1)的包时,才从堆栈中删除包。
  • 如果数据包中有间隙并且 (gap + 1) 数据包的时间戳大于某个阈值,则发送“重新传输请求”数据包以重新传输丢弃的数据包。

等一下……这正是 TCP 的工作方式(*)!你应该只使用 TCP!

(*) 这是一种简化,TCP 做了很多工作来使过程可靠。

【讨论】:

    【解决方案2】:

    UDP 无法做到这一点。如果您需要可靠的连接,您应该使用 TCP。

    【讨论】:

    • +1 尽管您仍然可以通过 UDP 实现使用序列号、确认和重传的连接。尽管毫无意义,但我不得不将其作为一项实验室作业来完成(花费大量时间和测试才能做到几乎与 TCP 一样好,这真的很痛苦)。
    【解决方案3】:

    UDP 是一种无连接协议。当没有连接时,您无法“检测”任何东西。您必须使用面向连接的协议(例如 TCP)来解决此问题。

    Comparison

    【讨论】:

      【解决方案4】:

      好的。我得到了它。但是我可以通过这样做来检查数据包丢失吗?例如,如果我将计时器设置为 2 秒,然后运行此函数,我可以查看服务器是否正确响应。那我应该知道有没有丢包?

      public bool IsResponseValid()
          {
              if(SNTPData.Length < SNTPDataLength || Mode != _Mode.Server)
              {
                  return false;
              }
              else
              {
                  return true;
              }
          }
      

      【讨论】:

      • 无法抗拒优化代码的冲动:return SNTPData.Length >= SNTPDataLength && Mode == _Mode.Server;
      【解决方案5】:

      因为没有办法测试 UDP 是否无法到达,唯一真正的选择是在所有发送的数据前面加上一个“数据包编号”,所以如果它不是下一个数字,你就知道它丢失了一个数据包..

      据我所知,没有办法故意丢失 1 个 udp 数据包,除了拔掉电缆并更换它.. 并希望..

      【讨论】:

        猜你喜欢
        • 2014-11-11
        • 2015-06-30
        • 2012-01-06
        • 2018-06-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多