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