在javascript中以良好的精度(> 0.5s)同步时间(类似NTP) [英] Synchronize time in javascript with a good precision (>0.5s) (NTP-like)

查看:20
本文介绍了在javascript中以良好的精度(> 0.5s)同步时间(类似NTP)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种方法来以良好的精度(假设至少为 0.5 秒)同步客户端之间的时间.

I'm looking for a way to synchronize time between clients with a good precision (let's say 0.5 seconds at least).

由于精度较差(一秒或更短),我排除在服务器响应标头中使用 jsontime 或利用时间戳.

I exclude using jsontime or exploiting timestamp in server response headers due to a poor precision (a second or maybe less).

更新:即使使用移动连接,它也应该工作.3G 连接本身的往返时间在 0.5 秒左右的情况并不少见(例如在意大利这里),因此算法必须稳健.

UPDATE: It should work even with mobile connections. It's not unfrequent (e.g. here in Italy) that 3G connections itself have a round trip time around 0.5s, so algorithm has to be robust.

推荐答案

求助于旧的 ICMP Timestamp 消息方案.在 JavaScript 和 PHP 中实现相当简单.

Resort to the good old ICMP Timestamp message scheme. It's fairly trivial to implement in JavaScript and PHP.

这是使用 JavaScript 和 PHP 实现此方案的一个实现:

Here's an implementation of this scheme using JavaScript and 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 代码:

<?php
    $receive = round(microtime(true) * 1000);
    echo $_POST["original"] . '|';
    echo $receive . '|';
    echo round(microtime(true) * 1000);
?>

我还没有测试过上面的代码,但它应该可以工作.

I haven't tested the above code, but it should work.

注意:如果实际发送和接收消息的时间相同或大致相同,以下方法将准确计算客户端和服务器之间的时间差.考虑以下场景:

Note: The following method will accurately calculate the time difference between the client and the server provided that actual time to send and receive messages is the same or approximately the same. Consider the following scenario:

  Time    Client   Server
-------- -------- --------
Original        0        2
Receive         3        5
Transmit        4        6
Returned        7        9

  1. 如您所见,客户端和服务器时钟有 2 个单位不同步.因此,当客户端发送时间戳请求时,它会将原始时间记录为 0.
  2. 服务器在 3 个单位后收到请求,但将接收时间记录为 5 个单位,因为它提前了 2 个单位.
  3. 然后它在一个单位后传输时间戳回复,并将传输时间记录为 6 个单位.
  4. 客户端在 3 个单位后收到回复(即根据服务器在 9 个单位).但是,由于它比服务器落后 2 个单位,因此将返回的时间记录为 7 个单位.

使用这些数据,我们可以计算:

Using this data, we can calculate:

Sending = Receive - Original = 5 - 0 = 5
Receiving = Returned - Transmit = 7 - 6 = 1
Roundtrip = Sending + Receiving = 5 + 1 = 6

从上面可以看出,发送和接收时间的计算不正确,具体取决于客户端和服务器不同步的程度.但是,往返时间总是正确的,因为我们首先添加两个单位(接收 + 原始),然后减去两个单位(返回 - 发送).

As you can see from above, the sending and receiving times are calculated incorrectly depending upon how much the client and server are off sync. However, the roundtrip time will always be correct because we are first adding two units (receive + original), and then subtracting two units (returned - transmit).

如果我们假设单程时间总是往返时间的一半(即发送时间就是接收时间,那么我们可以很容易地计算出时间差如下):

If we assume that the oneway time is always half of the roundtrip time (i.e. the time to transmit is the time to receive, then we can easily calculate the time difference as follows):

Oneway = Roundtrip / 2 = 6 / 2 = 3
Difference = Sending - Oneway = 5 - 3 = 2

如您所见,我们准确地将时间差计算为 2 个单位.时间差的方程式总是sending - oneway 时间.但是,此等式的准确性取决于您计算单程时间的准确程度.如果发送和接收消息的实际时间不相等或不大致相等,则您需要找到其他方法来计算单向时间.但是,就您的目的而言,这应该足够了.

As you can see, we accurately calculated the time difference as 2 units. The equation for time difference is always sending - oneway time. However, the accuracy of this equation depends upon how accurately you calculate the oneway time. If the actual time to send and receive the messages is not equal or approximately equal, you'll need to find some other way to calculate the one way time. However, for your purposes this should suffice.

这篇关于在javascript中以良好的精度(> 0.5s)同步时间(类似NTP)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆