我正在寻找一种可以以很高的精度(至少可以说0.5秒)在客户端之间同步时间的方法。
由于精度不佳(一秒或更短),我不使用jsontime或在服务器响应标头中利用时间戳。
更新:即使在移动连接下也可以使用。3G连接本身具有0.5s左右的往返时间并不罕见(例如,在意大利),因此算法必须健壮。
求助于旧的ICMP Timestamp消息方案。用JavaScript和PHP实现非常简单。
这是使用JavaScript和PHP的此方案的实现:
// browser.js var request = new XMLHttpRequest(); request.onreadystatechange = readystatechangehandler; request.open("POST", "http://www.example.com/sync.php", true); request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); request.send("original=" + (new Date).getTime()); function readystatechangehandler() { var returned = (new Date).getTime(); if (request.readyState === 4 && request.status === 200) { var timestamp = request.responseText.split('|'); var original = + timestamp[0]; var receive = + timestamp[1]; var transmit = + timestamp[2]; var sending = receive - original; var receiving = returned - transmit; var roundtrip = sending + receiving; var oneway = roundtrip / 2; var difference = sending - oneway; // this is what you want // so the server time will be client time + difference } }
现在查看sync.php代码:
sync.php
<?php $receive = round(microtime(true) * 1000); echo $_POST["original"] . '|'; echo $receive . '|'; echo round(microtime(true) * 1000); ?>
我还没有测试上面的代码,但是应该可以。
注意: 如果发送和接收消息的实际时间相同或大约相同,则以下方法将准确计算客户端与服务器之间的时间差。请考虑以下情形:
Time Client Server -------- -------- -------- Original 0 2 Receive 3 5 Transmit 4 6 Returned 7 9
使用此数据,我们可以计算:
Sending = Receive - Original = 5 - 0 = 5 Receiving = Returned - Transmit = 7 - 6 = 1 Roundtrip = Sending + Receiving = 5 + 1 = 6
从上面可以看到,发送和接收时间的计算不正确,具体取决于客户端和服务器不同步的程度。但是,往返时间将始终是正确的,因为我们首先要添加两个单位(接收+原始),然后减去两个单位(返回- 发送)。
如果我们假设单向时间始终是往返时间的一半(即,发送时间是接收时间,那么我们可以很容易地计算出时差,如下所示):
Oneway = Roundtrip / 2 = 6 / 2 = 3 Difference = Sending - Oneway = 5 - 3 = 2
如您所见,我们准确地将时差计算为2个单位。时差方程始终是sending - oneway时间。但是,此方程式的精度取决于您计算单向时间的精度。如果发送和接收消息的实际时间不相等或近似相等,则需要找到其他方法来计算单向时间。但是,出于您的目的,这已足够。
sending - oneway