Resort al buon vecchio schema di messaggio ICMP Timestamp. È abbastanza semplice da implementare in JavaScript e PHP.
Ecco un'implementazione di questo schema utilizzando JavaScript e 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
}
}
Ora, per il codice sync.php
:
<?php
$receive = round(microtime(true) * 1000);
echo $_POST["original"] . '|';
echo $receive . '|';
echo round(microtime(true) * 1000);
?>
Non ho ancora testato il codice di cui sopra, ma dovrebbe funzionare.
Nota: Il metodo seguente calcolerà con precisione la differenza di tempo tra il client e il server a condizione che il tempo effettivo per inviare e ricevere messaggi è lo stesso o circa lo stesso. Si consideri il seguente scenario:
Time Client Server
-------- -------- --------
Original 0 2
Receive 3 5
Transmit 4 6
Returned 7 9
- Come si può vedere, gli orologi client e server sono 2 unità al largo di sincronizzazione. Quindi quando il client invia la richiesta di data/ora, registra l'ora originale come 0.
- Il server riceve la richiesta 3 unità più tardi, ma registra il tempo di ricezione come 5 unità perché è di 2 unità avanti.
- Quindi trasmette la risposta data/ora una unità dopo e registra il tempo di trasmissione come 6 unità.
- Il client riceve la risposta dopo 3 unità (cioè a 9 unità in base al server). Tuttavia, dal momento che sono 2 unità dietro il server, registra il tempo restituito come 7 unità.
Utilizzando questi dati, possiamo calcolare:
Sending = Receive - Original = 5 - 0 = 5
Receiving = Returned - Transmit = 7 - 6 = 1
Roundtrip = Sending + Receiving = 5 + 1 = 6
Come si può vedere da sopra, i tempi di invio e ricezione sono calcolati in modo non corretto a seconda di quanto il client e il server sono fuori sincronia. Tuttavia, il tempo di andata e ritorno sarà sempre corretto perché stiamo aggiungendo prima due unità (ricevi + originale) e quindi sottraendo due unità (restituite - trasmetti).
Se assumiamo che il tempo unidirezionale è sempre metà del tempo di andata e ritorno (cioè il tempo per trasmettere il momento di ricevere, allora si può facilmente calcolare la differenza di tempo come segue):
Oneway = Roundtrip/2 = 6/2 = 3
Difference = Sending - Oneway = 5 - 3 = 2
Come puoi vedere, abbiamo calcolato con precisione la differenza di tempo come 2 unità. L'equazione per la differenza di orario è sempre sending - oneway
. Tuttavia, la precisione di questa equazione dipende da quanto accuratamente si calcola il tempo di percorrenza. Se il tempo effettivo di invio e ricezione dei messaggi non è uguale o approssimativamente uguale, sarà necessario trovare un altro modo per calcolare il tempo di sola andata.Tuttavia, per i tuoi scopi questo dovrebbe essere sufficiente.
Come posso inviare pacchetti ICMP da javascript? Ho visto solo un ActiveX chiamato ActiveSocket per l'invio di pacchetti ICMP, ma non posso usare ActiveX.It funziona su webkit. – micred
Non si inviano pacchetti ICMP. È sufficiente utilizzare lo stesso metodo utilizzato da ICMP per sincronizzare l'ora sul server e sul client. Spero che cancelli il tuo dubbio. Saluti. ;) –
La tua formattazione in PHP sembra errata: 'microtime()' senza parametri restituisce una stringa del modulo "0uuuuu ssssssssss". Preferirei "echo round (microtime (true) * 1000)". –