Java NTP 客户端

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/925191/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 21:09:58  来源:igfitidea点击:

Java NTP client

javantp

提问by Matt Howells

I need my software to communicate with an NTP server to determine the local clock offset. I have tried using the org.apache.commons.net.ntp package, but its implementation is rather poor when running on Windows, because of the use of System.currentTimeMillis() to determine the time before and after the NTP packet exchange. As you may or may not know, this value is only updated when the system clock ticks, which on most modern Win2k3 servers is at 64Hz or every 15.625ms. This greatly limits the accuracy of the clock offset calculation.

我需要我的软件与 NTP 服务器通信以确定本地时钟偏移。我曾尝试使用 org.apache.commons.net.ntp 包,但在 Windows 上运行时它的实现相当糟糕,因为使用 System.currentTimeMillis() 来确定 NTP 数据包交换前后的时间。你可能知道也可能不知道,这个值只在系统时钟滴答时更新,在大多数现代 Win2k3 服务器上,它是 64Hz 或每 15.625ms。这极大地限制了时钟偏移计算的准确性。

Ntpd uses the CPU high-frequency timer to interpolate between system clock ticks, and achieve much higher resolution time. Do you know of a Java implementation that uses this or a similar technique? Or do you know of any other NTP implementation other than Apache's?

Ntpd 使用 CPU 高频计时器在系统时钟滴答之间进行插值,并实现更高的分辨率时间。您知道使用这种技术或类似技术的 Java 实现吗?或者您知道除 Apache 之外的任何其他 NTP 实现吗?

回答by Brian Agnew

If you're using Java 5 or above, can you use System.nanoTime()to perform a more accurate measurement of time offsets ? You'd have to modify your existing NTP code, but you should have the source for it, and I wouldn't expect this to be difficult.

如果您使用的是 Java 5 或更高版本,是否可以使用System.nanoTime()来执行更准确的时间偏移测量?您必须修改现有的 NTP 代码,但您应该拥有它的源代码,我不认为这会很困难。

回答by dfa

there is a NTP Java implementation on support.ntp.org

support.ntp.org上有一个 NTP Java 实现

回答by Jan Schejbal

Since this question ranks very high on Google for "Java NTP client":

由于这个问题在 Google 上的“Java NTP 客户端”排名非常高:

Android has a nice, compact Apache-licensed implementation of a Simple NTP client: android.net.SntpClient.

Android 有一个很好的、紧凑的 Apache 许可的简单 NTP 客户端实现:android.net.SntpClient

It would need to be modified to run on non-Android java, but this should be trivial, since the code is about 100 lines of code plus another 100 lines of detailed comments, with no external dependencies except the Android system clock - and by chance, it is ready to accept relative timers like nanoTime()since it already uses such a relative timer.

它需要修改才能在非 Android java 上运行,但这应该是微不足道的,因为代码大约有 100 行代码加上另外 100 行详细注释,除了 Android 系统时钟之外没有任何外部依赖 - 并且是偶然的,它已经准备好接受相对定时器,nanoTime()因为它已经使用了这样的相对定时器。

回答by user2179737

I have written a java implementation (Java 7) that you can use: SntpClient

我编写了一个可以使用的 Java 实现(Java 7):SntpClient

回答by Teocci

I know this is an old question but I notice that all the answers does not explain how to use those libraries. In this answer we will show a basic implementation and its logic behind.

我知道这是一个老问题,但我注意到所有答案都没有解释如何使用这些库。在这个答案中,我们将展示一个基本的实现及其背后的逻辑。

A simple way to implement it is using Apache Commons Net library. This library will provide a NTPUDPClientclass to manage connectionless NTP requests and return a TimeInfoinstance. This instance should compute the offset between your system's time and the NTP server's time. Lets try to implement it here:

实现它的一种简单方法是使用Apache Commons Net 库。这个库将提供一个NTPUDPClient类来管理无连接的 NTP 请求并返回一个TimeInfo实例。此实例应计算系统时间与 NTP 服务器时间之间的偏移量。让我们尝试在这里实现它:

  1. Add the Apache Commons Net libraryto your project.
  1. Apache Commons Net 库添加到您的项目中。
<dependency>
  <groupId>commons-net</groupId>
  <artifactId>commons-net</artifactId>
  <version>3.6</version>
</dependency>
  1. Create a new instance of the NTPUDPClientclass.
  2. Setup the default timeout and the InetAddressof the NTP Server.
  3. Call the NTPUDPClient.getTime()method to retrieve a TimeInfoinstance with the time information from the specified server.
  4. Call computeDetails()method to compute and validate details of the NTP message packet.
  5. Finally, get the offsetand calculate an atomic time.
  1. 创建类的新实例NTPUDPClient
  2. 设置默认超时和InetAddressNTP 服务器。
  3. 调用该NTPUDPClient.getTime()方法以TimeInfo从指定服务器检索具有时间信息的实例。
  4. 调用computeDetails()方法来计算和验证 NTP 消息包的详细信息。
  5. 最后,得到offset并计算一个原子时间。

Here we have a basic implementation:

这里我们有一个基本的实现:

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;
  }
}

You will get something like that:

你会得到这样的东西:

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