package context.arch.comm.protocol;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.IOException;
/**
* This class implements a threaded serversocket that accepts TCP packets.
* It does nothing with the TCP packets themselves but can be subclassed
* to do real work. Whenever it receives data, it clones itself. The original
* class listens for more new connections while the clone handles the received
* data.
*
* @see java.lang.Runnable
* @see java.lang.Cloneable
*/
public class TCPServerSocket implements Runnable, Cloneable {
/**
* Debug flag. Set to true to see debug messages.
*/
public static boolean DEBUG = false;
/**
* The default port number to use is 5555
*/
public static final int DEFAULT_PORT = 5555;
private ServerSocket serverSocket;
private Thread runner = null;
private Socket data = null;
private int portNumber;
/**
* Default constructor for TCPServerSocket, with the default port.
*
* @see #DEFAULT_PORT
*/
public TCPServerSocket() {
portNumber = DEFAULT_PORT;
}
/**
* TCPServerSocket constructor with user-specified port.
*
* @param port Port number to use
*/
public TCPServerSocket(int port) {
portNumber = port;
}
/**
* Starts a ServerSocket and a thread with this TCPServerSocket as the
* Runnable.
*
*/
public void start() {
if (runner == null) {
try {
serverSocket = new ServerSocket(portNumber);
runner = new Thread(this);
runner.start();
} catch (IOException ioe) {
System.out.println("TCPServerSocket init error: "+ioe + " on port number "+portNumber);
}
}
}
/**
* Stops the original thread (just the original?) running and closes the socket.
*/
public void stopServer() {
if (serverSocket != null) {
runner = null;
try {
serverSocket.close();
} catch (IOException ioe) {
System.out.println("TCPServerSocket stopServer error: "+ioe);
}
}
}
/**
* This method loops forever waiting for data on the socket. When data
* arrives, it clones a new instance of TCPServerSocket so the new
* thread can deal with the data, while the current instance looks for new
* data. The new thread deals with the data by calling handleIncomingRequest().
*
* @see #handleIncomingRequest(java.net.Socket)
*/
public void run() {
if (serverSocket != null) {
while (true) {
try {
Socket dataSocket = serverSocket.accept();
TCPServerSocket newSocket = (TCPServerSocket) clone();
newSocket.serverSocket = null;
newSocket.data = dataSocket;
newSocket.runner = new Thread(newSocket);
newSocket.runner.start();
} catch (IOException ioe) {
System.out.println("TCPServerSocket run IOexception: "+ioe);
} catch (CloneNotSupportedException cnse) {
System.out.println("TCPServerSocket run CloningException: "+cnse);
}
}
}
else {
handleIncomingRequest(data);
}
}
/**
* This method handles data received on a given TCPServerSocket.
* Could be abstract since the method does nothing. A subclass is
* expected to override this method to handle the incoming data as
* necessary.
*
* @param data Socket the data is arriving on
*/
public void handleIncomingRequest(Socket data) {
if (DEBUG) {
System.out.println("in TCPServerSocket handleIncomingRequest(data)");
}
}
}