Java NTP client
Asked Answered
S

5

22

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.

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?

Schema answered 29/5, 2009 at 9:38 Comment(3)
Can you not submit a patch to the Apache Commons library?Venusian
Given time to implement and test it, and the willingness of my corporate overlords, yes I could.Schema
I asked a similar Question on Software Recommendations Stack Exchange.Ardell
I
11

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

Inimitable answered 29/5, 2009 at 9:49 Comment(1)
Alas, it is a naive implementation of SNTP. But +1 for finding it, thanks.Schema
H
10

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

Android has a nice, compact Apache-licensed implementation of a Simple NTP client: 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.

Hideout answered 15/6, 2013 at 9:48 Comment(3)
How do you replace SystemClock.elapsedRealtime(); ?Sight
SntpClient is annotated with @hide, so we can't use it (cleanly).Psittacosis
@KevinRobatel The idea isn't directly using it; the reason why I mentioned the license is that you can include a private "forked" copy of it (with package name adjusted, and any other changes you need like a different timer). That's the approach I took when I had to use it.Hideout
A
4

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

Antilogy answered 27/11, 2014 at 17:5 Comment(0)
A
4

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 go through a basic implementation and its logic behind.

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

  1. Add the Apache Commons Net library to your project.
<dependency>
  <groupId>commons-net</groupId>
  <artifactId>commons-net</artifactId>
  <version>3.6</version>
</dependency>
  1. Create a new instance of the NTPUDPClient class.
  2. Setup the default timeout and the InetAddress of the NTP Server.
  3. Call the NTPUDPClient.getTime() method to retrieve a TimeInfo instance 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 offset and calculate an atomic time.

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
Agonic answered 11/7, 2019 at 1:15 Comment(1)
it worked for me, in my case i needed Today date from server and not from system. If any one change system time my code failed. This code is great for me.Shipmate
E
3

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.

Earthshaker answered 29/5, 2009 at 9:47 Comment(4)
Yes, System.nanoTime() accesses the high-frequency timer, and I would expect this to be used for timestamping in a decent Java NTP implementation. However, this is non-trivial so I am hoping someone else has already done and debugged it.Schema
Yes. I couldn't find any obvious implementations though. A chance for fame and respect, maybe ? :-)Earthshaker
System.nanoTime() can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time so cannot be used to compare local system time to absolute time from a NTP server.Pawnshop
It can be used to calculate the time at any moment given the NTP time from a previous moment and the elapsed time between the two moments calculated using System.nanoTime()Weisberg

© 2022 - 2024 — McMap. All rights reserved.