Skip to content

Instantly share code, notes, and snippets.

Created March 31, 2014 23:16
Show Gist options
  • Save anonymous/9904508 to your computer and use it in GitHub Desktop.
Save anonymous/9904508 to your computer and use it in GitHub Desktop.
# Эта приблуда - клиент, который получает время с удаленной машины
# Смотреть будем на миллисекунды
require 'net/http'
measures = []
roundtrips = []
uri = URI.parse "http://сервервремени:2000"
# Спецификация NTP какбэ рекомендует спрашивать время несколько раз, минимум 8.
8.times do
local_time = Time.now.utc.to_f * 1000 # время до выполнения запроса
remote_time = Net::HTTP.get_response(uri).body.to_f # результат с сервера времени
now_time = Time.now.utc.to_f * 1000 # время после обработки запроса
measures << ((remote_time - local_time) + (remote_time - now_time))/2 # вычисление оффсета (смотри NTP БЛЕА)
roundtrips << (now_time - local_time) # время путешествия пакетов
p "before request: #{local_time}"
p "remote time: #{remote_time}"
p "now: #{now_time}"
p "req time: #{now_time-local_time}"
p "Remote-req: #{remote_time - local_time}"
p "req-now: #{now_time - remote_time}"
p "offset: #{measures.last}"
p "trip: #{roundtrips.last}"
p "-----"
end
# А теперь в чистовом варианте с применением усредненного оффсета и половины времени прохождения пакетов
local_time = Time.now.utc.to_f * 1000 # время до выполнения запроса
remote_time = Net::HTTP.get_response(uri).body.to_f # результат с сервера времени
now_time = Time.now.utc.to_f * 1000 # время после обработки запроса
avg_offset = measures[1..-1].reduce(:+).to_f / measures.size # среднее арифметическое от оффсета
avg_trip = roundtrips[1..-1].reduce(:+).to_f / roundtrips.size # среднее арифметическое от времени пути
p "Now - remote time: #{now_time - remote_time}"
p "Now - corrected time: #{now_time - (remote_time + avg_offset + (avg_trip/2)) }"
# очень простой сервер времени
require 'webrick'
server = WEBrick::HTTPServer.new :Port => 2000
server.mount_proc "/" do |req, res|
res.body = (Time.now.utc.to_f * 1000).to_s
end
trap('INT') { server.stop }
server.start
Пробуем на локальном сервере
"Now - remote time: 0.119873046875"
"Now - corrected time: 0.00341796875"
Пробуем на удаленном (время с локальным синхронизировано через ntp)
"Now - remote time: 198.780029296875"
"Now - corrected time: 37.198974609375"
Вывод:
С помошью нехитрых вычислений, уровень погрешности при получении времени с сервера понизился в несколько раз. Все, что сделано - это по сути отфильтрована сетевая задержка. Так как клиент-сервер написаны на руби, то они сами по себе нещадно глючат.
В любом случае, это всего-лишь показывает, что передача времени в чистом виде через HTTP-запрос без фильтрации врет как собака.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment