import java.io.IOException; import java.io.InterruptedIOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; public interface TimeServer { /** * @return current time from specific server. */ public long getCurrentTime (); /** * @return delay in response from specific server */ public double getDelay (); } class LocalTime implements TimeServer { public long getCurrentTime () { return System.currentTimeMillis(); } public double getDelay () { return 0; } } class InternetTime implements TimeServer { private double myRoundTripDelay = 0; private String myHost; public InternetTime (String host) { myHost = host; } public long getCurrentTime () { try { // Send request DatagramSocket socket = new DatagramSocket(); InetAddress address = InetAddress.getByName(myHost); byte[] buf = new NtpMessage().toByteArray(); DatagramPacket packet = new DatagramPacket(buf, buf.length, address, NtpMessage.NTP_PORT); // Set the transmit timestamp *just* before sending the packet // ToDo: Does this actually improve performance or not? NtpMessage.encodeTimestamp(packet.getData(), 40, (System.currentTimeMillis()/1000.0) + NtpMessage.SECONDS_1900_TO_EPOCH); socket.send(packet); // Get response packet = new DatagramPacket(buf, buf.length); socket.setSoTimeout(10*1000); try { socket.receive(packet); } catch (InterruptedIOException iie) { socket.close(); return -1; } // Immediately record the incoming timestamp double destinationTimestamp = (System.currentTimeMillis()/1000.0) + NtpMessage.SECONDS_1900_TO_EPOCH; // Process response NtpMessage msg = new NtpMessage(packet.getData()); socket.close(); myRoundTripDelay = (destinationTimestamp-msg.originateTimestamp) - (msg.receiveTimestamp-msg.transmitTimestamp); return (long)((msg.transmitTimestamp - NtpMessage.SECONDS_1900_TO_EPOCH)*1000); } catch (IOException ioe) { //ioe.printStackTrace(); return -1; } } public double getDelay () { return myRoundTripDelay; } }