View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.net.time;
19  
20  import java.io.DataOutputStream;
21  import java.io.IOException;
22  import java.net.ServerSocket;
23  import java.net.Socket;
24  
25  import org.apache.commons.io.IOUtils;
26  
27  /**
28   * The TimetSimpleServer class is a simple TCP implementation of a server for the Time Protocol described in RFC 868.
29   * <p>
30   * Listens for TCP socket connections on the time protocol port and writes the local time to socket outputStream as 32-bit integer of seconds since midnight on
31   * 1 January 1900 GMT. See <A HREF="ftp://ftp.rfc-editor.org/in-notes/rfc868.txt"> the spec </A> for details.
32   * <p>
33   * Note this is for <B>debugging purposes only</B> and not meant to be run as a realiable time service.
34   */
35  public class TimeTestSimpleServer implements Runnable {
36  
37      /**
38       * baseline time 1900-01-01T00:00:00 UTC
39       */
40      public static final long SECONDS_1900_TO_1970 = 2208988800L;
41  
42      /** The default time port. It is set to 37 according to RFC 868. */
43      public static final int DEFAULT_PORT = 37;
44  
45      public static void main(final String[] args) {
46          final TimeTestSimpleServer server = new TimeTestSimpleServer();
47          try {
48              server.start();
49          } catch (final IOException e) {
50              // ignored
51          }
52      }
53  
54      private ServerSocket server;
55      private final int port;
56  
57      private boolean running;
58  
59      public TimeTestSimpleServer() {
60          port = DEFAULT_PORT;
61      }
62  
63      public TimeTestSimpleServer(final int port) {
64          this.port = port;
65      }
66  
67      public void connect() throws IOException {
68          if (server == null) {
69              server = new ServerSocket(port);
70          }
71      }
72  
73      public int getPort() {
74          return server == null ? port : server.getLocalPort();
75      }
76  
77      public boolean isRunning() {
78          return running;
79      }
80  
81      @Override
82      public void run() {
83          Socket socket = null;
84          while (running) {
85              try {
86                  socket = server.accept();
87                  final DataOutputStream os = new DataOutputStream(socket.getOutputStream());
88                  // add 500 ms to round off to nearest second
89                  final int time = (int) ((System.currentTimeMillis() + 500) / 1000 + SECONDS_1900_TO_1970);
90                  os.writeInt(time);
91                  os.flush();
92              } catch (final IOException e) {
93                  // ignored
94              } finally {
95                  IOUtils.closeQuietly(socket, e -> System.err.println("close socket error: " + e));
96              }
97          }
98      }
99  
100     /*
101      * Start time service and provide time to client connections.
102      */
103     public void start() throws IOException {
104         if (server == null) {
105             connect();
106         }
107         if (!running) {
108             running = true;
109             new Thread(this).start();
110         }
111     }
112 
113     /*
114      * Close server socket.
115      */
116     public void stop() {
117         running = false;
118         if (server != null) {
119             IOUtils.closeQuietly(server, e -> System.err.println("close socket error: " + e));
120             server = null;
121         }
122     }
123 
124 }