TimeClientpublic class TimeClient extends Object Request time service, per RFC 868. RFC 868
(http://www.ietf.org/rfc/rfc0868.txt) is a very simple time protocol
whereby one system can request the current time from another system.
Most Linux, BSD and Solaris systems provide RFC 868 time service
on port 37. This simple program will inter-operate with those.
The National Institute of Standards and Technology (NIST) operates
a public time server at time.nist.gov.
The RFC 868 protocol specifies a 32 bit unsigned value be sent,
representing the number of seconds since Jan 1, 1900. The Java
epoch begins on Jan 1, 1970 (same as unix) so an adjustment is
made by adding or subtracting 2,208,988,800 as appropriate. To
avoid shifting and masking, a four-byte slice of an
eight-byte buffer is used to send/recieve. But getLong()
is done on the full eight bytes to get a long value.
When run, this program will issue time requests to each hostname
given on the command line, then enter a loop to receive packets.
Note that some requests or replies may be lost, which means
this code could block forever.
Created: April 2002 |
Fields Summary |
---|
private static final int | DEFAULT_TIME_PORT | private static final long | DIFF_1900 | protected int | port | protected List | remoteHosts | protected DatagramChannel | channel |
Constructors Summary |
---|
public TimeClient(String[] argv)
if (argv.length == 0) {
throw new Exception ("Usage: [ -p port ] host ...");
}
parseArgs (argv);
this.channel = DatagramChannel.open();
|
Methods Summary |
---|
public void | getReplies()
// allocate a buffer to hold a long value
ByteBuffer longBuffer = ByteBuffer.allocate (8);
// assure big-endian (network) byte order
longBuffer.order (ByteOrder.BIG_ENDIAN);
// zero the whole buffer to be sure
longBuffer.putLong (0, 0);
// position to first byte of the low-order 32 bits
longBuffer.position (4);
// slice the buffer, gives view of the low-order 32 bits
ByteBuffer buffer = longBuffer.slice();
int expect = remoteHosts.size();
int replies = 0;
System.out.println ("");
System.out.println ("Waiting for replies...");
while (true) {
InetSocketAddress sa;
sa = receivePacket (channel, buffer);
if (sa == null) {
// only get here if receivePacket timed out
System.out.println ("Time's up, "
+ (expect - replies)
+ " replies never arrived");
break;
}
buffer.flip();
replies++;
printTime (longBuffer.getLong (0), sa);
if (replies == expect) {
System.out.println ("All packets answered");
break;
}
// some replies haven't shown up yet
System.out.println ("Received " + replies
+ " of " + expect + " replies");
}
| public static void | main(java.lang.String[] argv)
TimeClient client = new TimeClient (argv);
client.sendRequests();
client.getReplies();
| protected void | parseArgs(java.lang.String[] argv)
remoteHosts = new LinkedList();
for (int i = 0; i < argv.length; i++) {
String arg = argv [i];
// send client requests to the given port
if (arg.equals ("-p")) {
i++;
this.port = Integer.parseInt (argv [i]);
continue;
}
// create an address object for the host name
InetSocketAddress sa = new InetSocketAddress (arg, port);
// validate that it has an address
if (sa.getAddress() == null) {
System.out.println ("Cannot resolve address: "
+ arg);
continue;
}
remoteHosts.add (sa);
}
| protected void | printTime(long remote1900, java.net.InetSocketAddress sa)
// local time as seconds since Jan 1, 1970
long local = System.currentTimeMillis() / 1000;
// remote time as seconds since Jan 1, 1970
long remote = remote1900 - DIFF_1900;
Date remoteDate = new Date (remote * 1000);
Date localDate = new Date (local * 1000);
long skew = remote - local;
System.out.println ("Reply from "
+ sa.getHostName() + ":" + sa.getPort());
System.out.println (" there: " + remoteDate);
System.out.println (" here: " + localDate);
System.out.print (" skew: ");
if (skew == 0) {
System.out.println ("none");
} else if (skew > 0) {
System.out.println (skew + " seconds ahead");
} else {
System.out.println ((-skew) + " seconds behind");
}
| protected java.net.InetSocketAddress | receivePacket(java.nio.channels.DatagramChannel channel, java.nio.ByteBuffer buffer)
buffer.clear();
// receive an unsigned 32-bit, big-endian value
return ((InetSocketAddress) channel.receive (buffer));
| protected void | sendRequests()
ByteBuffer buffer = ByteBuffer.allocate (1);
Iterator it = remoteHosts.iterator();
while (it.hasNext()) {
InetSocketAddress sa = (InetSocketAddress) it.next();
System.out.println ("Requesting time from "
+ sa.getHostName() + ":" + sa.getPort());
// make it empty, see RFC868
buffer.clear().flip();
// fire and forget
channel.send (buffer, sa);
}
|
|