【发布时间】:2016-08-11 02:24:24
【问题描述】:
我构建了一个 HTML5 多人游戏,它依赖于服务器和客户端之间相当准确的时间同步。在大多数情况下,我使用的算法非常准确——它所做的只是估计客户端-服务器时间增量是多少,即服务器上的当前时间与客户端上的当前时间之间的差异。例如,如果服务器时间正好比客户端时间早 5 秒,则时间增量为 5000 毫秒。
客户端和服务器 (node.js) 都是用 Javascript 编写的。该算法的工作原理如下:
在客户端记录时间:
var clientTime = Date.now();-
Ping 服务器。当服务器收到消息时,它立即发送一个响应,其中只包含一件事:收到消息时服务器上的时间。
var serverTime = Date.now(); // Send serverTime to the client 当客户端收到服务器响应时,立即记录时间:
var clientTime2 = Date.now();
现在,我们知道当服务器收到消息时,客户端时间必须在clientTime和clientTime2之间。
如果服务器在客户端时间为clientTime 时收到消息(即客户端->服务器请求以某种方式花费了 0 毫秒),则时间增量为
var delta1 = (serverTime - clientTime);
如果服务器在客户端时间为clientTime 时收到消息(即服务器->客户端响应以某种方式花费了 0 毫秒),则时间增量为
var delta2 = (serverTime - clientTime2).
因此我们可以肯定地说时间增量介于delta1 和delta2 之间。现在,重复这个过程多次,每次都根据你得到的结果缩小范围,你可以很好地估计时间增量。
我已经在 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