All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ilex.net.BasicServer Maven / Gradle / Ivy

Go to download

A collection of software for aggregatting and processing environmental data such as from NOAA GOES satellites.

The newest version!
/*
*  $Id$
*
*  $Source$
*
*  $State$
*
*  $Log$
*  Revision 1.3  2009/08/26 11:04:06  mjmaloney
*  Collections
*
*  Revision 1.2  2008/04/23 11:23:57  cvs
*  dev
*
*  Revision 1.1  2008/04/04 18:21:09  cvs
*  Added legacy code to repository
*
*  Revision 1.22  2007/06/07 11:50:20  mmaloney
*  Added getPort() method.
*
*  Revision 1.21  2005/11/21 19:14:59  mmaloney
*  LRGS 5.4 release prep
*
*  Revision 1.20  2005/07/10 14:21:48  mjmaloney
*  Don't use IllegalArgumentException -- it's not checked.
*
*  Revision 1.19  2005/01/07 18:45:21  mjmaloney
*  Added getSvrThreads() method to iterate through all clients.
*
*  Revision 1.18  2004/08/30 14:50:22  mjmaloney
*  Javadocs
*
*  Revision 1.17  2004/05/25 13:03:59  mjmaloney
*  LRIT Release Prep
*
*  Revision 1.16  2004/05/17 22:59:09  mjmaloney
*  Default for -h arg set to "localhost"
*
*  Revision 1.15  2004/03/01 20:18:16  mjmaloney
*  Upgraded socket apps to flush data after each interaction.
*
*  Revision 1.14  2003/12/18 19:38:55  mjmaloney
*  Added BasicSvrThread.getParent() and BasicServer.getNumClients() methods.
*
*  Revision 1.13  2003/05/01 13:58:56  mjmaloney
*  Rethrow IOExecption if listen throws for reason other than shutdown.
*
*  Revision 1.12  2003/05/01 13:57:05  mjmaloney
*  No err msg if IOException on listen() because of shutdown.
*
*  Revision 1.11  2001/03/13 03:05:29  mike
*  Fixed bug - was instantiating server thread twice.
*
*  Revision 1.10  2000/09/08 13:11:03  mike
*  Release prep
*
*  Revision 1.9  2000/06/07 15:09:00  mike
*  Removed diagnostic.
*
*  Revision 1.8  2000/06/07 12:13:25  mike
*  Removed stdout message "Added thread"
*
*  Revision 1.7  2000/05/31 21:14:27  mike
*  dev
*
*  Revision 1.6  2000/01/19 14:34:37  mike
*  Debug messages to detect garbage collection.
*
*  Revision 1.5  1999/12/06 15:07:08  mike
*  Removed println diagnostics
*
*  Revision 1.4  1999/10/22 17:28:22  mike
*  10/22/1999
*
*  Revision 1.3  1999/10/09 17:03:40  mike
*  10/9/1999
*
*  Revision 1.2  1999/09/30 18:16:44  mike
*  9/30/1999
*
*  Revision 1.1  1999/09/20 17:20:01  mike
*  Initial
*
*
*/

package ilex.net;

import ilex.net.BasicSvrThread;
import java.net.*;
import java.util.LinkedList;
import java.util.Iterator;
import java.io.*;

/**
The BasicServer class is intended to be sub-classed by more complete
servers. It provides the basic functionality for:
  • Listening on a well-known port
  • Accepting new clients
  • Handling client disconnects
*/ public abstract class BasicServer { /** The port number to listen on */ protected int portNum; /** The listening socket */ protected ServerSocket listeningSocket; /** List of BasicSvrThread objects, one for each client connection. */ protected LinkedList mySvrThreads; /** The listening thread */ private Thread listeningThread; /** The bind address if one is specified. */ private InetAddress bindaddr; /** Should be set by concrete subclass calling setModuleName() */ String module = "BasicServer"; /** * The constructor will throw IllegalArgumentException if port is * <= 0. It will throw an IOException if it cannot create a listening * socket on the specified port. * @param port the port to listen on */ public BasicServer( int port ) throws IllegalArgumentException, IOException { this(port, null); } /** * This version of the constructor allows you to specify the inet * address for the listening socket. This should be used if your * host has more than one network connection and you need to specify * which to use. * @param port port to listen on * @param bindaddr used if you have multiple NICs and only want to listen * on one. */ public BasicServer( int port, InetAddress bindaddr ) throws IOException { if (port <= 0) throw new IOException( "BasicServer: port number must be a positive integer."); portNum = port; this.bindaddr = bindaddr; makeServerSocket(); mySvrThreads = new LinkedList(); listeningThread = null; } /** * Makes the server (listening) socket. * @throws IllegalArgumentException if bad bindaddr or port number. * @throws IOException if can't open. */ protected void makeServerSocket( ) throws IllegalArgumentException, IOException { listeningSocket = new ServerSocket(portNum, 50, bindaddr); } /** * The listen method continually waits for new clients and accepts * them. When a new client is accepted, the serviceNewClient method * is called. *

* If you have set a timeout on the listening socket, this method * will call the listenTimeout method when a timeout occurs. Your * sub-class should override listenTimeout to perform periodic * functions while listening. * Other IOExceptions indicate error conditions on the listening * socket and should be handled by the caller. * @throws IOException if IO error on listening socket. */ public void listen( ) throws IOException { while(listeningSocket != null) // shutdown() will null the socket { try { listeningThread = Thread.currentThread(); Socket client = listeningSocket.accept(); listeningThread = null; serviceNewClient(client); } catch(InterruptedIOException intr) { listenTimeout(); } catch(IOException ioe) { // only rethrow if IOE is NOT due to shutdown. if (listeningSocket != null) throw ioe; } } } /** Guarantees that listening socket is shut down before object destroyed. */ public void finalize( ) { if (listeningSocket != null) shutdown(); } /** * The shutdown method will disconnect all client threads and close * the listening socket. */ public void shutdown( ) { killAllSvrThreads(); ServerSocket tsock = listeningSocket; listeningSocket = null; if (listeningThread != null) listeningThread.interrupt(); try { Thread.sleep(100L); } catch(InterruptedException ie) {} try { if (tsock != null) tsock.close(); } catch(IOException ioe) {} } /** * This is the low-level method called when a new client has * connected to the server. The default action taken here is to * call your over-ridden 'newSvrThread()' method, which should * create a new thread object to handle the client. * Override this method only if you need more low-level control. * @param client the new client connection */ protected void serviceNewClient( Socket client ) throws IOException { BasicSvrThread bst = newSvrThread(client); if (bst != null) { addSvrThread( bst ); bst.start(); } } /** * rmSvrThread is typically called from the child thread object * when it wants to die. It must be synchronized to protect the * vector. * @param bst the BasicSvrThread to remove. */ public synchronized void rmSvrThread( BasicSvrThread bst ) { boolean wasthere = mySvrThreads.remove(bst); } /** * This method replaces the old 'getSvrThreads' method. The old method * was unsafe because iterating the list could cause a * ConcurrentModificationException when a client asynchronously disconnects. * * @return a clone of the LinkedList containing the server threads. */ public synchronized LinkedList getAllSvrThreads() { return (LinkedList)mySvrThreads.clone(); } /** * addSvrThreads is called internally when a new client is created. * MJM 20020226 - must be synchronized. Other threads may be traversing * the list via the iterators. Threads that do so should synchronize * on the server object. * @param bst the BasicSvrThread to remove. */ private synchronized void addSvrThread( BasicSvrThread bst ) { mySvrThreads.add(bst); } /** Shuts down and removes all server threads. */ public void killAllSvrThreads( ) { while(mySvrThreads.size() > 0) { BasicSvrThread bst = (BasicSvrThread)mySvrThreads.getFirst(); bst.disconnect(); // This should have called rmSvrThread() above. ...But make sure: rmSvrThread(bst); } } /** * @return number of clients currently connected. */ public int getNumSvrThreads( ) { return mySvrThreads.size(); } /** * @return iterator into list of threads */ public Iterator getSvrThreads() { return mySvrThreads.iterator(); } //=============================================================== // The following methods should be over-ridden by your sub-class: //=============================================================== /** * This method is called if you have set a timeout on the * ServerSocket object and a timeout occurs. The default * implementation does nothing. */ protected void listenTimeout( ) { } /** * Override this method to create a new thread object to handle * interaction with a client. You should sub-class BasicSvrThread * and create an instance of your sub-class here. * If there is a problem in creating the object and you want * to reject the connection return null. * If a fatal error occurs and you want to abort the server listen() * method, throw IOException. * @param sock the socket for the new client connection. * @return BasicSvrThread (or concrete subclass) object * @throws IOException if error opening IO streams for this socket. */ protected abstract BasicSvrThread newSvrThread( Socket sock ) throws IOException; public int getPort() { return portNum; } protected void setModuleName(String nm) { module = nm; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy