Java NTP client
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?
there is a NTP Java implementation on support.ntp.org
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.
I have written a java implementation (Java 7) that you can use: SntpClient
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.
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 NTPUDPClient
class to manage connectionless NTP requests and return a TimeInfo
instance. This instance should compute the offset between your system's time and the NTP server's time. Lets try to implement it here:
- Add the Apache Commons Net library to your project.
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
</dependency>
- Create a new instance of the
NTPUDPClient
class. - Setup the default timeout and the
InetAddress
of the NTP Server. - Call the
NTPUDPClient.getTime()
method to retrieve aTimeInfo
instance with the time information from the specified server. - Call
computeDetails()
method to compute and validate details of the NTP message packet. - 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