Синхронизация времени

Тема данной статьи – синхронизация времени между клиентской машинкой и сервером. В инете покопавшись ничего не смог найти путного. Итак.

Допустим нам необходимо, что на ход дается 30 секунд (для пошаговой игры) или допустим скорость бега персонажа 3 условных метра в секунду (для реал-тайм). В любом случае необходимо синхронизировать время.

Первое решение – «в лоб». Просто запрашиваем сервер и получаем от него ответ, сколько сейчас времени по его мнению. Разницу в величинах запоминаем и используем при расчетах.
Минусы данного метода – не учитывается время, затрачено на «путь» запроса.

Поэтому назревает второе решение. Запоминаем текущее время t0 – посылаем запрос на сервер и берем его время ts – смотрим, сколько сейчас времени на клиенте – t1.
time_for_path = t1-t0, следовательно diff _time = (ts - time_for_path/2) – t0) , предположив что запрос шел до сервера с той же скорость, что и от сервера к нам. (Время обработки сервером запроса принимаем равное 0 – у нас быстрые сервера ;) ).

В чем тут подвох? На самом деле запрос мог идти до сервера за f0, а от сервера f1 причем f0 может отличаться от f1 на несколько порядков. В сумме f0+f1, конечно дадут time_for_path (тут примем, что обработка клиентом запроса также равна 0), но нам желательно учитывать именно обратную скорость f1.

римерчик
Предположим, что на сервере часы отличаются на 103 ms, т.е. t0 = 1000, а ts = 1103.
Также предположим, что скорость запроса f0 = 5ms, f1 = 2 ms, следовательно, t1 = 1007.
Для клиента t0 = 1000, time_for_path = 7, следовательно t1 = 1007
Для сервера ts` = ts+f0 = 1103 + 5 =1108
diff_time = ts’ - f0 – t0 = ts` – time_for_path/2 - t0 = 1108 – 3 – 1000 = 105, что довольно близко к истине.

Узнать более точно нам помогут N запросов отправленных и полученных, самый точный вариант дала бы калибровка из множества запросов, причем отлавливая плохие результаты - например, методом Стьюдента.