I'm attempting to grab a timestamp off an nist.gov server using the code below.
InetAddress addr = InetAddress.getByName("129.6.15.30");
DatagramSocket s = new DatagramSocket();
System.out.println("Connected to: "+addr.getHostName());
byte[] buf = new byte[4];
DatagramPacket p = new DatagramPacket(buf, buf.length, addr, 37);
s.send(p);
System.out.println("message sent");
DatagramPacket dp = new DatagramPacket(buf, buf.length);
s.receive(dp);
String data = new String(dp.getData(), 0, dp.getLength());
System.out.println("Received: "+data);
When I run this on Eclipse, I get the following back in the console.
Connected to: time-c.nist.gov
message sent
Received: ÛÏÌ<
Good news is, I'm connecting to the correct server and getting back a packet. However, I just can't seem to turn that packet's data into a comprehensible representation of that data. What am I missing?
The response from the Time Protocol is a 32 bit integer in network byte order - this is not a string.
To read it you need to use something like DataInputStream
:
DataInputStream dis = new DataInputStream(new ByteArrayInputStream(dp.getData(), 0, dp.getLength()));
int time = dis.readInt();
dis.close();
The time value returned is the number of seconds since 1st Jan 1900, to get a Java Instant
from this we need to convert the unsigned integer to the standard Java 'epoch' which is the number of seconds since 1st Jan 1970:
long secondsSince1Jan1900 = Integer.toUnsignedLong(time);
long differenceBetweenEpochs = 2208988800L;
long secondsSince1Jan1970 = secondsSince1Jan1900 - differenceBetweenEpochs;
Instant instant = Instant.ofEpochSecond(secondsSince1Jan1970);