001 /*
002 * Copyright 2001-2005 The Apache Software Foundation
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.apache.commons.net;
017
018 import java.io.IOException;
019 import java.net.DatagramPacket;
020 import java.net.InetAddress;
021 import java.util.Date;
022
023 /***
024 * The TimeUDPClient class is a UDP implementation of a client for the
025 * Time protocol described in RFC 868. To use the class, merely
026 * open a local datagram socket with
027 * {@link org.apache.commons.net.DatagramSocketClient#open open }
028 * and call {@link #getTime getTime } or
029 * {@link #getTime getDate } to retrieve the time. Then call
030 * {@link org.apache.commons.net.DatagramSocketClient#close close }
031 * to close the connection properly. Unlike
032 * {@link org.apache.commons.net.TimeTCPClient},
033 * successive calls to {@link #getTime getTime } or
034 * {@link #getDate getDate } are permitted
035 * without re-establishing a connection. That is because UDP is a
036 * connectionless protocol and the Time protocol is stateless.
037 * <p>
038 * <p>
039 * @author Daniel F. Savarese
040 * @see TimeTCPClient
041 ***/
042
043 public final class TimeUDPClient extends DatagramSocketClient
044 {
045 /*** The default time port. It is set to 37 according to RFC 868. ***/
046 public static final int DEFAULT_PORT = 37;
047
048 /***
049 * The number of seconds between 00:00 1 January 1900 and
050 * 00:00 1 January 1970. This value can be useful for converting
051 * time values to other formats.
052 ***/
053 public static final long SECONDS_1900_TO_1970 = 2208988800L;
054
055 private byte[] __dummyData = new byte[1];
056 private byte[] __timeData = new byte[4];
057
058 /***
059 * Retrieves the time from the specified server and port and
060 * returns it. The time is the number of seconds since
061 * 00:00 (midnight) 1 January 1900 GMT, as specified by RFC 868.
062 * This method reads the raw 32-bit big-endian
063 * unsigned integer from the server, converts it to a Java long, and
064 * returns the value.
065 * <p>
066 * @param host The address of the server.
067 * @param port The port of the service.
068 * @return The time value retrieved from the server.
069 * @exception IOException If an error occurs while retrieving the time.
070 ***/
071 public long getTime(InetAddress host, int port) throws IOException
072 {
073 long time;
074 DatagramPacket sendPacket, receivePacket;
075
076 sendPacket =
077 new DatagramPacket(__dummyData, __dummyData.length, host, port);
078 receivePacket = new DatagramPacket(__timeData, __timeData.length);
079
080 _socket_.send(sendPacket);
081 _socket_.receive(receivePacket);
082
083 time = 0L;
084 time |= (((__timeData[0] & 0xff) << 24) & 0xffffffffL);
085 time |= (((__timeData[1] & 0xff) << 16) & 0xffffffffL);
086 time |= (((__timeData[2] & 0xff) << 8) & 0xffffffffL);
087 time |= ((__timeData[3] & 0xff) & 0xffffffffL);
088
089 return time;
090 }
091
092 /*** Same as <code> getTime(host, DEFAULT_PORT); </code> ***/
093 public long getTime(InetAddress host) throws IOException
094 {
095 return getTime(host, DEFAULT_PORT);
096 }
097
098
099 /***
100 * Retrieves the time from the server and returns a Java Date
101 * containing the time converted to the local timezone.
102 * <p>
103 * @param host The address of the server.
104 * @param port The port of the service.
105 * @return A Date value containing the time retrieved from the server
106 * converted to the local timezone.
107 * @exception IOException If an error occurs while fetching the time.
108 ***/
109 public Date getDate(InetAddress host, int port) throws IOException
110 {
111 return new Date((getTime(host, port) - SECONDS_1900_TO_1970)*1000L);
112 }
113
114
115 /*** Same as <code> getTime(host, DEFAULT_PORT); </code> ***/
116 public Date getDate(InetAddress host) throws IOException
117 {
118 return new Date((getTime(host, DEFAULT_PORT) -
119 SECONDS_1900_TO_1970)*1000L);
120 }
121
122 }
123