Java NTP客户端

时间:2009-05-29 09:38:33

标签: java ntp

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

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

5 个答案:

答案 0 :(得分:10)

support.ntp.org

上有一个NTP Java实现

答案 1 :(得分:9)

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

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

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

答案 2 :(得分:3)

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

答案 3 :(得分:3)

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

答案 4 :(得分:0)

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

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

  1. Apache Commons Net library添加到您的项目中。
<dependency>
  <groupId>commons-net</groupId>
  <artifactId>commons-net</artifactId>
  <version>3.6</version>
</dependency>
  1. 创建NTPUDPClient类的新实例。
  2. 设置默认超时时间和NTP服务器的InetAddress
  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