【问题标题】:Inconsistent Date.now() values不一致的 Date.now() 值
【发布时间】:2016-08-11 02:24:24
【问题描述】:

我构建了一个 HTML5 多人游戏,它依赖于服务器和客户端之间相当准确的时间同步。在大多数情况下,我使用的算法非常准确——它所做的只是估计客户端-服务器时间增量是多少,即服务器上的当前时间与客户端上的当前时间之间的差异。例如,如果服务器时间正好比客户端时间早 5 秒,则时间增量为 5000 毫秒。

客户端和服务器 (node.js) 都是用 Javascript 编写的。该算法的工作原理如下:

  1. 在客户端记录时间: var clientTime = Date.now();

  2. Ping 服务器。当服务器收到消息时,它立即发送一个响应,其中只包含一件事:收到消息时服务器上的时间。

    var serverTime = Date.now();
    // Send serverTime to the client
    
  3. 当客户端收到服务器响应时,立即记录时间: var clientTime2 = Date.now();

现在,我们知道当服务器收到消息时,客户端时间必须clientTimeclientTime2之间。

如果服务器在客户端时间为clientTime 时收到消息(即客户端->服务器请求以某种方式花费了 0 毫秒),则时间增量为 var delta1 = (serverTime - clientTime);

如果服务器在客户端时间为clientTime 时收到消息(即服务器->客户端响应以某种方式花费了 0 毫秒),则时间增量为 var delta2 = (serverTime - clientTime2).

因此我们可以肯定地说时间增量介于delta1delta2 之间。现在,重复这个过程多次,每次都根据你得到的结果缩小范围,你可以很好地估计时间增量。

我已经在 7 种不同的浏览器和多台机器上对此进行了数百次测试,并且 从未 遇到过任何问题。从来没有前后矛盾。


但问题是,我的服务器日志显示,有时,一些人会非常获得不一致的时间同步结果。下面是一个玩家时间同步的实际示例:

客户端经历了上述算法的 74 个循环,并成功地将可能的时间增量范围缩小到:[-186460, -186431],没有任何不一致。 29ms 准确度

在第 75 个周期,可能是第 74 个周期之后的几秒钟,客户端计算出可能的时间增量范围为:[-601, -596]。 5ms 准确度,除了它与过去 74 次循环极为不一致:它是 3 分钟关闭!

我会把这归咎于疯狂的边缘情况,除非它每天发生近 100 次......这怎么会发生?使用Date.now()时会不会出现错误?

【问题讨论】:

  • 您几乎肯定需要发布您在整个过程中使用的实际代码,以获得明确的答案。任何没有看到代码的答案都只是猜测。
  • 那不准确; Date.now() 基于 UTC。当然,这取决于客户认为的时间。
  • 怎么样,发生了一次互联网时间同步,将时钟设置回正确的时间,因为它显然慢了 3 分钟。
  • 是否还有与这些随机不一致相关的其他数据?也许是一天中的一般时间(在您的服务器或客户端的时区)?一个或另一个(或两者?!)是否可以执行互联网时间同步并主要修复漂移?
  • 假设客户端和服务器有不同的时间,只要 Date.now() 永远不会“冻结”或者这个算法在理论上是完美的。

标签: javascript node.js html multiplayer


【解决方案1】:

performance.now() 而不是Date.now(),因为performance.now() 是单调递增的,不受时钟漂移的影响。看到cmets,感谢大家的帮助!

【讨论】:

    【解决方案2】:

    您的困难在于,您需要在往返时间不同的 Internet 上估算到服务器的往返时间。有时这种差异会出乎意料地大,例如临时拥塞和大型路由器缓冲区延迟单个消息比正常时间长得多的情况。 (参见“缓冲膨胀”。)

    您的第二个困难是您使用的是自我报告的客户时间,这意味着如果客户的时钟很奇怪,您会觉得往返估计出错了。正如另一位发帖人指出的那样,互联网时间协议有时会快速调整时钟以纠正本地计时异常。

    听起来您需要在代码中进行一些过滤,考虑到以前的结果,这样当您得到异常结果时,您不会立即接受它为真。

    【讨论】:

    • 有过滤,我不会自动接受它为真。不过,该算法根本不关心任何类型的拥塞或延迟。即使客户端 -> 服务器耗时 50 毫秒,服务器 -> 客户端耗时 6000 毫秒,仍然不会出现不一致(我已经对此进行了测试以仔细检查)。我能想到发生不一致的唯一方法是,无论出于何种原因,客户端或服务器时间都会立即向后/向前跳...
    • 这是网络时间协议如何处理时间变化的介绍,例如当本地时钟偏离实际时间时。 ntp.org/ntpfaq/NTP-s-algo.htm
    • 谢谢,您对阅读特定部分有什么建议吗?这篇文章好长哈哈
    • 是的!网络时间协议非常古老,并且文档匹配。看一下关于“6.操作系统时钟接口”的那一点。
    • 时间同步真的很难。不要假设您的本地实现接近正确。仔细研究 NTP 及其继承者。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-23
    相关资源
    最近更新 更多