Class TcpServer

java.lang.Object
  extended by TcpServer

public class TcpServer
extends java.lang.Object

A robust class for establishing a TCP server and manipulating its listening port. The TcpServer.Events and property change events make it an appropriate tool in a threaded, GUI application. It is almost identical in design to the UdpServer class which accompanies this one at iHarder.net.

To start a TCP server, create a new TcpServer and call start():

 TcpServer server = new TcpServer();
 server.start();

Of course it won't be much help unless you register as a listener so you'll know when a java.net.Socket has come in:

 server.addTcpServerListener( new TcpServer.Listener(){
     public void socketReceived( TcpServer.Event evt ){
         Socket socket = evt.getSocket();
         ...
     }   // end socket received
 });

The server runs on one thread, and all events may be fired on that thread if desired by setting the executor to null server.setExecutor(null). By default a cached thread pool is used (Executors.newCachedThreadPool()) so that when you handle a socketReceived event, you are already working in a dedicated thread.

The public methods are all synchronized on this, and great care has been taken to avoid deadlocks and race conditions. That being said, there may still be bugs (please contact the author if you find any), and you certainly still have the power to introduce these problems yourself.

It's often handy to have your own class extend this one rather than making an instance field to hold a TcpServer where you'd have to pass along all the setPort(...) methods and so forth.

The supporting TcpServer.Event and TcpServer.Listener classes are static inner classes in this file so that you have only one file to copy to your project. You're welcome.

Since the TcpServer.java, UdpServer.java, and NioServer.java are so similar, and since lots of copying and pasting was going on among them, you may find some comments that refer to TCP instead of UDP or vice versa. Please feel free to let me know, so I can correct that.

This code is released into the Public Domain. Since this is Public Domain, you don't need to worry about licensing, and you can simply copy this TcpServer.java file to your own package and use it as you like. Enjoy. Please consider leaving the following statement here in this code:

This TcpServer class was copied to this project from its source as found at iHarder.net.

Author:
Robert Harder, rharder@users.sourceforge.net
See Also:
TcpServer, TcpServer.Event, TcpServer.Listener

Nested Class Summary
static class TcpServer.Event
          An event representing activity by a TcpServer.
static interface TcpServer.Listener
          An interface for listening to events from a TcpServer.
static class TcpServer.State
          One of four possible states for the server to be in:
 
Field Summary
static java.lang.String EXECUTOR_PROP
          The Executor property executor used with the property change listeners and the preferences, if a preferences object is given.
static java.lang.String LAST_EXCEPTION_PROP
           
static java.lang.String PORT_PROP
          The port property port used with the property change listeners and the preferences, if a preferences object is given.
static java.lang.String STATE_PROP
           
 
Constructor Summary
TcpServer()
          Constructs a new TcpServer that will listen on the default port 1234 (but not until start() is called).
TcpServer(int port)
          Constructs a new TcpServer that will listen on the given port (but not until start() is called).
TcpServer(int port, java.util.concurrent.ThreadFactory factory)
          Constructs a new TcpServer that will listen on the given port (but not until start() is called).
 
Method Summary
 void addPropertyChangeListener(java.beans.PropertyChangeListener listener)
          Add a property listener.
 void addPropertyChangeListener(java.lang.String property, java.beans.PropertyChangeListener listener)
          Add a property listener for the named property.
 void addTcpServerListener(TcpServer.Listener l)
          Adds a TcpServer.Listener.
protected  void fireExceptionNotification(java.lang.Throwable t)
          Fires a property change event with the new exception.
 void fireProperties()
          Fires property chagne events for all current values setting the old value to null and new value to the current.
protected  void firePropertyChange(java.lang.String prop, java.lang.Object oldVal, java.lang.Object newVal)
          Fire a property change event on the current thread.
protected  void fireTcpServerSocketReceived()
          Fires event when a socket is received
 java.util.concurrent.Executor getExecutor()
          Returns the Executor (or null if none is set) that is used to execute the event firing.
 java.lang.Throwable getLastException()
          Returns the last exception (Throwable, actually) that the server encountered.
static java.util.logging.Level getLoggingLevel()
          Static method returning the logging level using Java's java.util.logging package.
 int getPort()
          Returns the port on which the server is or will be listening.
 java.net.Socket getSocket()
          Returns the last Socket received.
 TcpServer.State getState()
          Returns the current state of the server, one of STOPPED, STARTING, or STARTED.
 void removePropertyChangeListener(java.beans.PropertyChangeListener listener)
          Remove a property listener.
 void removePropertyChangeListener(java.lang.String property, java.beans.PropertyChangeListener listener)
          Remove a property listener for the named property.
 void removeTcpServerListener(TcpServer.Listener l)
          Removes a TcpServer.Listener.
 void reset()
          Resets the server, if it is running, otherwise does nothing.
protected  void runServer()
          This method starts up and listens indefinitely for TCP packets.
 void setExecutor(java.util.concurrent.Executor exec)
          Sets (or clears, if null) the Executor used to fire events.
static void setLoggingLevel(java.util.logging.Level level)
          Static method to set the logging level using Java's java.util.logging package.
 void setPort(int port)
          Sets the new port on which the server will attempt to listen.
protected  void setState(TcpServer.State state)
          Sets the state and fires an event.
 void start()
          Attempts to start the server listening and returns immediately.
 void stop()
          Attempts to stop the server, if the server is in the STARTED state, and returns immediately.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

PORT_PROP

public static final java.lang.String PORT_PROP
The port property port used with the property change listeners and the preferences, if a preferences object is given.

See Also:
Constant Field Values

EXECUTOR_PROP

public static final java.lang.String EXECUTOR_PROP
The Executor property executor used with the property change listeners and the preferences, if a preferences object is given.

See Also:
Constant Field Values

STATE_PROP

public static final java.lang.String STATE_PROP
See Also:
Constant Field Values

LAST_EXCEPTION_PROP

public static final java.lang.String LAST_EXCEPTION_PROP
See Also:
Constant Field Values
Constructor Detail

TcpServer

public TcpServer()
Constructs a new TcpServer that will listen on the default port 1234 (but not until start() is called). The I/O thread will not be in daemon mode.


TcpServer

public TcpServer(int port)
Constructs a new TcpServer that will listen on the given port (but not until start() is called). The I/O thread will not be in daemon mode.

Parameters:
port - the port on which to listen

TcpServer

public TcpServer(int port,
                 java.util.concurrent.ThreadFactory factory)
Constructs a new TcpServer that will listen on the given port (but not until start() is called). The provided ThreadFactory will be used when starting and running the server.

Parameters:
port - the port to listen to
factory - for creating the io thread
Method Detail

start

public void start()
Attempts to start the server listening and returns immediately. Listen for start events to know if the server was successfully started.

See Also:
TcpServer.Listener

stop

public void stop()
Attempts to stop the server, if the server is in the STARTED state, and returns immediately. Be sure to listen for stop events to know if the server was successfully stopped.

See Also:
TcpServer.Listener

getState

public TcpServer.State getState()
Returns the current state of the server, one of STOPPED, STARTING, or STARTED.

Returns:
state of the server

setState

protected void setState(TcpServer.State state)
Sets the state and fires an event. This method does not change what the server is doing, only what is reflected by the currentState variable.

Parameters:
state - the new server state

reset

public void reset()
Resets the server, if it is running, otherwise does nothing. This is accomplished by registering as a listener, stopping the server, detecting the stop, unregistering, and starting the server again. It's a useful design pattern, and you may want to look at the source code for this method to check it out.


runServer

protected void runServer()
This method starts up and listens indefinitely for TCP packets. On entering this method, the state is assumed to be STARTING. Upon exiting this method, the state will be STOPPING.


getSocket

public java.net.Socket getSocket()
Returns the last Socket received.

Returns:
the socket just received

getPort

public int getPort()
Returns the port on which the server is or will be listening.

Returns:
The port for listening.

setPort

public void setPort(int port)
Sets the new port on which the server will attempt to listen. If the server is already listening, then it will attempt to restart on the new port, generating start and stop events. If the old port and new port are the same, events will be fired, but the server will not actually reset.

Parameters:
port - the new port for listening
Throws:
java.lang.IllegalArgumentException - if port is outside 0..65535

getExecutor

public java.util.concurrent.Executor getExecutor()
Returns the Executor (or null if none is set) that is used to execute the event firing.

Returns:
Executor used for event firing or null

setExecutor

public void setExecutor(java.util.concurrent.Executor exec)

Sets (or clears, if null) the Executor used to fire events. If an Executor is set, then for each event, all listeners of that event are called in seqentially on a thread generated by the Executor.

Take the following example:

import java.util.concurrent.*; ... server.setExecutor( Executors.newCachedThreadPool() );

Let's say three objects are registered to listen for events from the TcpServer. When the server state changes, the three objects will be called sequentially on the same thread, generated by the Cached Thread Pool. Say one of those objects takes a long time to respond, and a new incoming connection is established while waiting. Those three objects will sequentially be notified of the new connection on a different thread, generated by the Cached Thread Pool.

Parameters:
exec - the new Executor or null if no executor is to be used

addTcpServerListener

public void addTcpServerListener(TcpServer.Listener l)
Adds a TcpServer.Listener.

Parameters:
l - the listener

removeTcpServerListener

public void removeTcpServerListener(TcpServer.Listener l)
Removes a TcpServer.Listener.

Parameters:
l - the listener

fireTcpServerSocketReceived

protected void fireTcpServerSocketReceived()
Fires event when a socket is received


fireProperties

public void fireProperties()
Fires property chagne events for all current values setting the old value to null and new value to the current.


firePropertyChange

protected void firePropertyChange(java.lang.String prop,
                                  java.lang.Object oldVal,
                                  java.lang.Object newVal)
Fire a property change event on the current thread.

Parameters:
prop - name of property
oldVal - old value
newVal - new value

addPropertyChangeListener

public void addPropertyChangeListener(java.beans.PropertyChangeListener listener)
Add a property listener.

Parameters:
listener - the property change listener

addPropertyChangeListener

public void addPropertyChangeListener(java.lang.String property,
                                      java.beans.PropertyChangeListener listener)
Add a property listener for the named property.

Parameters:
property - the sole property name for which to register
listener - the property change listener

removePropertyChangeListener

public void removePropertyChangeListener(java.beans.PropertyChangeListener listener)
Remove a property listener.

Parameters:
listener - the property change listener

removePropertyChangeListener

public void removePropertyChangeListener(java.lang.String property,
                                         java.beans.PropertyChangeListener listener)
Remove a property listener for the named property.

Parameters:
property - the sole property name for which to stop receiving events
listener - the property change listener

getLastException

public java.lang.Throwable getLastException()
Returns the last exception (Throwable, actually) that the server encountered.

Returns:
last exception

fireExceptionNotification

protected void fireExceptionNotification(java.lang.Throwable t)
Fires a property change event with the new exception.

Parameters:
t -

setLoggingLevel

public static void setLoggingLevel(java.util.logging.Level level)
Static method to set the logging level using Java's java.util.logging package. Example: TcpServer.setLoggingLevel(Level.OFF);.

Parameters:
level - the new logging level

getLoggingLevel

public static java.util.logging.Level getLoggingLevel()
Static method returning the logging level using Java's java.util.logging package.

Returns:
the logging level