Java NTP клиент

Мне нужно, чтобы мое программное обеспечение связывалось с NTP-сервером для определения смещения локальных часов. Я попытался использовать пакет org.apache.commons.net.ntp, но его реализация при работе в Windows довольно плохая из-за использования System.currentTimeMillis() для определения времени до и после обмена пакетами NTP. Как вы можете знать, а может и не знать, это значение обновляется только при тиках системных часов, которые на большинстве современных серверов Win2k3 имеют частоту 64 Гц или каждые 15,625 мс. Это значительно ограничивает точность вычисления смещения тактового сигнала.

Ntpd использует высокочастотный таймер ЦП для интерполяции между тактами системных часов и достижения гораздо более высокого времени разрешения. Знаете ли вы о реализации Java, которая использует эту или аналогичную технику? Или вы знаете о какой-либо другой реализации NTP, кроме Apache?

4 ответа

На support.ntp.org есть реализация NTP Java

Так как этот вопрос очень высоко оценивается в Google как "Java NTP client":

У Android есть хорошая, компактная Apache-лицензированная реализация Simple NTP-клиента: android.net.SntpClient.

Его нужно изменить, чтобы он работал на java, отличном от Android, но это должно быть тривиально, поскольку код содержит около 100 строк кода плюс еще 100 строк подробных комментариев, без внешних зависимостей, кроме системных часов Android, - и случайно готов принять относительные таймеры вроде nanoTime() так как он уже использует такой относительный таймер.

Я знаю, что это старый вопрос, но я заметил, что все ответы не объясняют, как использовать эти библиотеки. В этом ответе мы покажем базовую реализацию и ее логику.

Простой способ реализовать это - использовать библиотеку Apache Commons Net. Эта библиотека обеспечит NTPUDPClient класс для управления NTP-запросами без установления соединения и возврата TimeInfo экземпляр. Этот экземпляр должен вычислить смещение между временем вашей системы и временем NTP-сервера. Давайте попробуем реализовать это здесь:

  1. Добавьте библиотеку Apache Commons Net в свой проект.
<dependency>
  <groupId>commons-net</groupId>
  <artifactId>commons-net</artifactId>
  <version>3.6</version>
</dependency>
  1. Создайте новый экземпляр NTPUDPClient класс.
  2. Установите время ожидания по умолчанию и InetAddress сервера NTP.
  3. Позвоните NTPUDPClient.getTime() метод для получения TimeInfo экземпляр с информацией о времени с указанного сервера.
  4. Вызов computeDetails() метод для вычисления и проверки деталей пакета сообщений NTP.
  5. Наконец, получить offset и рассчитать атомное время.

Здесь у нас есть базовая реализация:

import java.net.InetAddress;
import java.util.Date;
import org.apache.commons.net.ntp.NTPUDPClient; 
import org.apache.commons.net.ntp.TimeInfo;

public class NTPClient {
  private static final String SERVER_NAME = "pool.ntp.org";

  private volatile TimeInfo timeInfo;
  private volatile Long offset;

  public static void main() throws Exception {

    NTPUDPClient client = new NTPUDPClient();
    // We want to timeout if a response takes longer than 10 seconds
    client.setDefaultTimeout(10_000);

    InetAddress inetAddress = InetAddress.getByName(SERVER_NAME);
    TimeInfo timeInfo = client.getTime(inetAddress);
    timeInfo.computeDetails();
    if (timeInfo.getOffset() != null) {
        this.timeInfo = timeInfo;
        this.offset = timeInfo.getOffset();
    }

    // This system NTP time
    TimeStamp systemNtpTime = TimeStamp.getCurrentTime();
    System.out.println("System time:\t" + systemNtpTime + "  " + systemNtpTime.toDateString());

    // Calculate the remote server NTP time
    long currentTime = System.currentTimeMillis();
    TimeStamp atomicNtpTime = TimeStamp.getNtpTime(currentTime + offset).getTime()

    System.out.println("Atomic time:\t" + atomicNtpTime + "  " + atomicNtpTime.toDateString());
  }

  public boolean isComputed()
  {
    return timeInfo != null && offset != null;
  }
}

Вы получите что-то подобное:

System time:    dfaa2c15.2083126e  Thu, Nov 29 2018 18:12:53.127
Atomic time:    dfaa2c15.210624dd  Thu, Nov 29 2018 18:12:53.129

Я написал реализацию Java (Java 7), которую вы можете использовать: SntpClient

Если вы используете Java 5 или выше, можете ли вы использовать System.nanoTime() для более точного измерения временных смещений? Вам придется изменить существующий код NTP, но у вас должен быть его источник, и я не ожидаю, что это будет сложно.

Другие вопросы по тегам