Со времени начала использования компьютеров (сперва в специализированных системах, в потом и в повседневной жизни) появилась задача поддерживать точность хода системных часов, т.е. иметь точно синхронизированное время с остальными компьютерами и системами. Особенно точность времени критична в распределенных системах, которые критичны к порядку вычисления задач, обработки данных и т.п.
Одним из примеров такой синхронизации, где впервые был применен популярный протокол синхронизации времени NTP, может быть диспетчерская служба управления полетами.
Также немаловажно, чтобы сама сеть компьютеров имела те только синхронизированное время, но и это время было точным с другими системами по всей планете. Т.е. время по всей территории планеты было одинаковым (или достаточно близким).
Первыми протоколами точного времени, используемым на компьютерах, были DAYTIME (RFC 867) и TIME (RFC 868). Первый предназначался для сообщения даты и времени в понятном человеку виде, второй - понятном компьютеру виде. Формат ответа DAYTIME строго не регламентируется и не предназначен для машинной обработки - предполагается лишь, что человеку, прочитавшему полученную строку, станет ясно текущее время.
Протокол TIME, напротив, предназначен для обмена времени между машинами. На подключившийся к TIME-серверу компьютер приходит UDP-пакет, содержащий единственное 32-битное беззнаковое число, соответствующе числу прошедших с 1 января 1900 г. секунд по UTC. Поскольку такое число переполняется через 136 лет, этот протокол способен функционировать только до 2036 г.
Понятно, что ни DAYTIME, ни TIME не могут обеспечить необходимую точность синхронизации времени. В связи с этим, в 1985 г. Дэвидом Л. Миллсом (David L. Mills) из университета Дэлавера был разработан сетевой протокол синхронизации времени NTP, точнее его начальная, позднее названная нулевой (NTPv0) версия, описанная в RFC 958. Протокол NTP использует алгоритм Марзулло (предложен Кейтом Марзулло (Keith Marzullo) из Университета Калифорнии, Сан-Диего), включая такую особенность, как учёт времени передачи. В версии 4 способен достигать точности 10 мс при работе через Интернет, и до 0,2 мс внутри локальных сетей.
Описывать сами протоколы, а тем более их работу и взаимодействие мы не будем - этому посвящено много статей в Интернете - начиная с официальных документов RFC и заканчивая обзорами. Отметим лишь, что NTP для синхронизации использует протокол UDP и 123 порт, DAYTIME - 13 порт TCP/UDP, TIME - 37 порт TCP/UDP.
Протокол NTP совершенствовался не один раз: NTPv1 (1988 г, RFC 1059), NTPv2 (1989 г., RFC1119), NTPv3 (1992 г., RFC1305), NTPv4 (1996 г., RFC2030).
Для определения точности или значимости того или иного NTP-сервера используют параметр Stratum (стратум) - целое число от 1 до 15. Стратум 1 соответствует серверам, имеющим непосредственно связь с эталонном времени, стратум 2 - сервер, получающий сведения о времени от серверов первого стратума и т.д. При построении цепочки связей значение стратума увеличивается на 1.
Работа алгоритма NTP достаточно проста и может быть проиллюстрированна задачей Рэймонда М. Смаллиана (1978 г.):
У одного человека не было наручных часов, но зато дома висели точные настенные часы, которые он иногда забывал заводить. Однажды, забыв очередной раз завести часы, он отправился в гости к своему другу, провел у того вечер, а вернувшись домой, сумел правильно поставить часы. Каким образом ему удалось это сделать, если время в пути заранее известно не было?
Ответ таков: выходя из дома, человек заводит часы и запоминает, в каком положении находятся стрелки. Придя к другу и уходя из гостей, он отмечает время своего прихода и ухода. Это позволяет ему узнать, сколько он находился в гостях. Вернувшись домой и взглянув на часы, человек определяет продолжительность своего отсутствия. Вычитая из этого времени то время, которое он провел в гостях, человек узнает время, затраченное на дорогу туда и обратно. Прибавив ко времени выхода из гостей половину времени, затраченного на дорогу, он получает возможность узнать время прихода домой и перевести соответствующим образом стрелки своих часов.
Таким образом, по четырём данным: время отправки запроса (по часам клиента); время получения запроса сервером (по часам сервера); время отправки ответа сервером (по часам сервера); время получения ответа (по часам клиента) можно найти время пакета в пути туда и обратно, а затем - откорректировать локальное время.
При этих расчетах мы пользуемся тремя важными предположениями:
На самом деле все эти предположения, строго говоря, не верны, и получить точное значение серверного времени с помощью одного NTP-запроса невозможно. Поэтому для синхронизации часов обычно используется несколько NTP-серверов, на которые постоянно шлются запросы. Накапливая статистику за длительное время, математическими методами можно определить точность показаний каждого из серверов, скорость хода часов на каждом из них, и т.п. величины, используя которые, можно добиться математически доказуемой точности синхронизации. Конкретные используемые методы описаны в RFC и чрезвычайно сложны. Кстати, из-за третьего предположения, использование синхронизации по NTP по несимметричным каналам связи (спутниковые и т.п.) не правомерно.
Кроме собственно обмена показаниями времени, в NTP начиная с версии 2 включён механизм обмена метаинформацией в виде "управляющих сообщений" NTP. Формат самих управляющих сообщений не задан в RFC, но существующий стандарт де-факто позволяет с их помощью запрашивать у NTP-сервера такие параметры, как адреса всех его клиентов и вышестоящих серверов, задержку до каждого из них и т.п.
NTP позволяет добиться высокоточной синхронизации времени в сети синхронизирующихся серверов, каждый из которых получает показания из нескольких источников, обрабатывает их, и передаёт дальше. Он применим только внутри небольших локальных сетей и сетей с малыми задержками пакетов; в Интернете он практически неприменим из-за большой (и, что важно, случайной) задержки пакетов, которая на порядки превосходит разницы в показаниях часов клиента и сервера. Такая NTP-сеть характеризуется масштабируемостью и устойчивостью к сбоям - даже в случае отказа часов одного из серверов остальные немедленно это заметят и перестанут использовать его показания.
Помимо NTP, существует упрощенная версия этого протокола - SNTP (Simple Network Time Protocol). Он реализован для синхронизации времени конечным клиентом, поскольку все преимущества протокола NTP проявляются именно в сети серверов, а для получения показаний конечным пользователем NTP излишне сложен. Поэтому для синхронизации времени конечными компьютерами и серверами был предложен протокол SNTP (SNTPv3: 1992 г., RFC1361 и 1995 г., RFC1769; SNTPv4 включён как подпротокол в NTPv4).
На самом деле SNTP - это не новый протокол, а способ использования NTP-пакетов и NTP-серверов в приложениях, где не требуется высокоточное время, либо оно недостижимо. В этом случае клиент использует только часть информации UDP-пакета NTP-сервера. SNTP-клиент может работать с любыми версиями NTP-серверов, и кроме них - с особыми SNTP-серверами, которые в откликах заполняют только необходимые данные UDP-пакета.
Таким образом, "облегченный" SNTP образует не сеть синхронизирующихся серверов, а пары "клиент-сервер". Любой NTP-сервер является одновременно SNTP-сервером. Клиент, который не передаёт полученное время дальше, может работать как NTP- или SNTP-клиент, в зависимости от условий. Для SNTP, как и для NTP, зарезервирован 123-й UDP-порт.