- Timestamp:
- 09/17/11 15:19:05 (8 months ago)
- Branch:
- default
- Convert:
- svn:7c3792e6-d75b-4784-96a6-b298f655ee64/trunk@2775
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kraken-ntp/src/main/java/org/krakenapps/ntp/NtpClient.java
r274 r341 17 17 18 18 import java.io.IOException; 19 import java.net.DatagramPacket; 20 import java.net.DatagramSocket; 19 21 import java.net.InetAddress; 22 import java.net.SocketTimeoutException; 23 import java.net.UnknownHostException; 24 import java.text.SimpleDateFormat; 25 import java.util.Arrays; 26 import java.util.Calendar; 20 27 import java.util.Date; 28 29 import org.krakenapps.ntp.impl.ServerTime; 30 import org.slf4j.Logger; 31 import org.slf4j.LoggerFactory; 21 32 22 33 /** 23 34 * @author delmitz 24 35 */ 25 public interface NtpClient { 26 InetAddress getTimeServer(); 27 28 int getTimeout(); 29 30 void setTimeServer(InetAddress server); 31 32 void setTimeout(int millisecond); 33 34 Date sync(); 35 36 void setSystemTime(Date date) throws IOException; 36 public class NtpClient { 37 private static final String DEFAULT_TIME_SERVER = "pool.ntp.org"; 38 private static final int NTP_V3_PACKET = 3; 39 private static final int CLIENT_MODE = 3; 40 private static final int STRATUM_INDEX = 1; 41 private static final int POLL_INDEX = 2; 42 private static final int PRECISION_INDEX = 3; 43 private static final int ROOT_DELAY_INDEX = 4; 44 private static final int ROOT_DISPERSION_INDEX = 8; 45 private static final int REFERENCE_IDENTIFIER_INDEX = 12; 46 private static final int REFERENCE_TIMESTAMP_INDEX = 16; 47 private static final int ORIGINATE_TIMESTAMP_INDEX = 24; 48 private static final int RECEIVE_TIMESTAMP_INDEX = 32; 49 private static final int TRANSMIT_TIMESTAMP_INDEX = 40; 50 51 private Logger logger = LoggerFactory.getLogger(NtpClient.class); 52 53 private InetAddress timeServer; 54 private int timeout; 55 56 public NtpClient() throws UnknownHostException { 57 this(null); 58 } 59 60 public NtpClient(String timeServer) throws UnknownHostException { 61 this(timeServer, 5000); 62 } 63 64 public NtpClient(String timeServer, int timeout) throws UnknownHostException { 65 if (timeServer == null) 66 timeServer = DEFAULT_TIME_SERVER; 67 this.timeServer = InetAddress.getByName(timeServer); 68 this.timeout = timeout; 69 } 70 71 public InetAddress getTimeServer() { 72 return timeServer; 73 } 74 75 public void setTimeServer(InetAddress timeServer) { 76 this.timeServer = timeServer; 77 } 78 79 public int getTimeout() { 80 return timeout; 81 } 82 83 public void setTimeout(int timeout) { 84 this.timeout = timeout; 85 } 86 87 public void setSystemTime(Date time) throws IOException { 88 String os = System.getProperty("os.name"); 89 if (os.contains("Windows")) { 90 String newDate = new SimpleDateFormat("MM-dd-yy").format(time); 91 Runtime.getRuntime().exec("cmd /c date " + newDate); 92 93 String newTime = new SimpleDateFormat("HH:mm:ss.SSS").format(time); 94 newTime = newTime.substring(0, newTime.length() - 1); 95 Runtime.getRuntime().exec("cmd /c time " + newTime); 96 } else if (os.contains("Linux")) { 97 String newTime = new SimpleDateFormat("MMddHHmmyyyy.ss").format(time); 98 Runtime.getRuntime().exec("date " + newTime); 99 } else { 100 // just pray 101 String newTime = new SimpleDateFormat("MMddHHmmyyyy.ss").format(time); 102 Runtime.getRuntime().exec("date " + newTime); 103 } 104 } 105 106 public Date sync() { 107 try { 108 ServerTime time = getTime(); 109 setSystemTime(addOffset(time)); 110 logger.info("kraken ntp: The time has been successfully synchronized with {} on {}", timeServer, 111 new SimpleDateFormat("yyyy/MM/dd HH:mm:ss.SSS 'UTC'").format(time.getTransmit())); 112 return time.getTransmit(); 113 } catch (SocketTimeoutException e) { 114 logger.error("kraken ntp: receive timeout.", e); 115 } catch (IOException e) { 116 logger.error("kraken ntp: sync failed.", e); 117 } 118 119 return null; 120 } 121 122 private ServerTime getTime() throws IOException { 123 DatagramSocket socket = new DatagramSocket(); 124 socket.setSoTimeout(timeout); 125 transmit(socket, timeServer, 123); 126 ServerTime time = receive(socket); 127 time.setDestination(getUtcTimeMillis()); 128 return time; 129 } 130 131 private void transmit(DatagramSocket socket, InetAddress addr, int port) throws IOException { 132 byte[] buf = new byte[48]; 133 buf[0] |= NTP_V3_PACKET; // set NTP Packet version 3 134 buf[0] |= (CLIENT_MODE << 3); // set Client mode 135 136 long now = getUtcTimeMillis(); 137 now += 2209021200000L; // baseline 1970 to 1900 138 139 long l = (now / 1000) << 32; 140 l |= ((now % 1000) << 32) / 1000; 141 for (int i = 7; i >= 0; i--) { // set Transmit Timestamp 142 buf[TRANSMIT_TIMESTAMP_INDEX + i] = (byte) (l & 0xff); 143 l >>>= 8; 144 } 145 146 DatagramPacket p = new DatagramPacket(buf, buf.length); 147 p.setAddress(addr); 148 p.setPort(port); 149 socket.send(p); 150 } 151 152 private long getUtcTimeMillis() { 153 return System.currentTimeMillis() - Calendar.getInstance().getTimeZone().getOffset(0); 154 } 155 156 private ServerTime receive(DatagramSocket socket) throws IOException, SocketTimeoutException { 157 byte[] buf = new byte[48]; 158 DatagramPacket p = new DatagramPacket(buf, buf.length); 159 socket.receive(p); 160 161 ServerTime time = new ServerTime(); 162 time.setStratum((int) buf[STRATUM_INDEX]); 163 time.setPoll(buf[POLL_INDEX]); 164 time.setPrecision(buf[PRECISION_INDEX]); 165 time.setRootDelay(Arrays.copyOfRange(buf, ROOT_DELAY_INDEX, ROOT_DELAY_INDEX + 4)); 166 time.setRootDispersion(Arrays.copyOfRange(buf, ROOT_DISPERSION_INDEX, ROOT_DISPERSION_INDEX + 4)); 167 time.setReferenceIdentifier(Arrays.copyOfRange(buf, REFERENCE_IDENTIFIER_INDEX, REFERENCE_IDENTIFIER_INDEX + 4)); 168 time.setReference(ntpTimeToJavaDate(buf, REFERENCE_TIMESTAMP_INDEX)); 169 time.setOriginate(ntpTimeToJavaDate(buf, ORIGINATE_TIMESTAMP_INDEX)); 170 time.setReceive(ntpTimeToJavaDate(buf, RECEIVE_TIMESTAMP_INDEX)); 171 time.setTransmit(ntpTimeToJavaDate(buf, TRANSMIT_TIMESTAMP_INDEX)); 172 173 return time; 174 } 175 176 private long ntpTimeToJavaDate(byte[] buf, int offset) { 177 long seconds = 0; 178 for (int i = 0; i < 4; i++) { 179 seconds = seconds << 8; 180 seconds |= buf[offset + i] & 0xff; 181 } 182 seconds *= 1000L; 183 seconds -= 2209021200000L; // baseline 1900 to 1970 184 185 long fraction = 0; 186 for (int i = 4; i < 8; i++) { 187 fraction = fraction << 8; 188 fraction |= buf[offset + i] & 0xff; 189 } 190 fraction *= 1000; 191 fraction >>>= 32; 192 193 return (seconds + fraction); 194 } 195 196 private Date addOffset(ServerTime time) { 197 long millis = System.currentTimeMillis() + time.getClockOffset(); 198 return new Date(millis); 199 } 37 200 }
Note: See TracChangeset
for help on using the changeset viewer.
