Подтвердить что ты не робот

Клиент Java NTP

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

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

4b9b3361

Ответ 1

существует реализация NTP Java на support.ntp.org

Ответ 2

Поскольку этот вопрос очень высок для Google для "Java NTP client":

Android имеет приятную, компактную версию Apache с простым клиентом NTP: android.net.SntpClient.

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

Ответ 3

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

Ответ 4

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

Ответ 5

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

Простой способ реализовать это - использовать библиотеку 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