Ответ 1
Прибегать к старой схеме 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
:
<?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
- Как вы можете видеть, часы клиента и сервера синхронизируются на 2 единицы. Следовательно, когда клиент отправляет запрос метки времени, он записывает исходное время как 0.
- Сервер получает запрос на 3 единицы позже, но записывает время приема как 5 единиц, потому что он на 2 единицы впереди.
- Затем он передает ответ метки времени на один блок позже и записывает время передачи как 6 единиц.
- Клиент получает ответ после 3 единиц (т.е. на 9 единиц по серверу). Однако, поскольку он занимает 2 единицы позади сервера, он регистрирует возвращаемое время как 7 единиц.
Используя эти данные, мы можем вычислить:
Sending = Receive - Original = 5 - 0 = 5
Receiving = Returned - Transmit = 7 - 6 = 1
Roundtrip = Sending + Receiving = 5 + 1 = 6
Как вы можете видеть выше, время отправки и получения вычисляется неверно в зависимости от того, насколько клиент и сервер отключены. Тем не менее, время округления всегда будет правильным, потому что мы сначала добавляем две единицы (получаем + оригинал), а затем вычитаем две единицы (возвращаем - передавать).
Если предположить, что время oneway всегда является половиной времени округления (т.е. время для передачи - это время для приема, то мы можем легко вычислить разницу во времени следующим образом):
Oneway = Roundtrip / 2 = 6 / 2 = 3
Difference = Sending - Oneway = 5 - 3 = 2
Как вы можете видеть, мы точно вычислили разницу во времени как 2 единицы. Уравнение для разницы во времени всегда sending - oneway
времени. Однако точность этого уравнения зависит от того, насколько точно вы рассчитываете время в пути. Если фактическое время отправки и получения сообщений не равно или приблизительно равно, вам нужно найти другой способ рассчитать одностороннее время. Однако для ваших целей это должно быть достаточно.