----------------------------------------------- The One Class Server ----------------------------------------------- EchoServer.java ----------------------------------------------- ----------------------------------------------- import java.io.*; import java.io.*; public class EchoServer extends Server { // A single argument: the port on which to listen public EchoServer( int port ) { super( port ); } // This function is called for each new connection; it // implements whatever functionality is needed from the server. // In this case, it simply sends back to the client all data // that the client sends it. If it receives a ´q´, the // whole server is shut down. public void PRocess( InputStream in, OutputStream out ) { try { while (true) { int c = in.read(); if (c==´q´) { close(); } else { out.write( c ); } } } catch( IOException ie ) { System.out.println( ie ); } } // Command-line: "java EchoServer <port>" static public void main( String args[] ) throws Exception { int port = new Integer( args[0] ).intValue(); new EchoServer( port ); } } Server类的实现是很有趣的,因为它对于所有线程使用了一个Server类的实例。
----------------------------------------------- The One Class Server ----------------------------------------------- The Listener Thread ----------------------------------------------- ----------------------------------------------- import java.io.*; import java.net.*; import java.util.*; abstract public class Server implements Runnable { // The port the server will listen on private int port; // Used to "pass" a Socket to the new thread that will process it private Hashtable handoff = new Hashtable(); // The first thread -- we store it here so we can kill it // first when closing. private Thread listener; // A list of the Threads that have been started private Vector threads = new Vector(); // A list of the Sockets that have connected to us private Vector sockets = new Vector(); // The listen socket private ServerSocket ss; public Server( int port ) { this.port = port; // Start the listener thread. Because we haven´t passed a Socket // object to this thread in the handoff table, it will know // that it is to be the listener thread. listener = new Thread( this ); listener.start(); } synchronized public void close() { // First, make sure there aren´t any incoming connections listener.stop(); // Now, close all the sockets for (Enumeration e = sockets.elements(); e.hasMoreElements();){ Socket s = (Socket)e.nextElement(); try { s.close(); } catch( IOException ie ) { System.out.println( ie );} } // And stop all the threads for (Enumeration e = threads.elements(); e.hasMoreElements();){ Thread t = (Thread)e.nextElement(); // But let´s not stop *ourselves* yet! if (t != Thread.currentThread()) t.stop(); } System.out.println( "Shutting down!" ); // Now we can stop ourselves. Thread.currentThread().stop(); } // This routine does the actual work of the server. It´s not // implemented, so you have to extend this class to actually get // something done. abstract public void process( InputStream in, OutputStream out ); // This routine processes all the connections. All the threads // started by this class run this same routine of the same instance // of Server. public void run() { // Get the Socket that is being "passed" to us by the listener // thread. If there is no Socket here for us, then we ARE the // listener thread, or at least we are about to be. Socket s = (Socket)handoff.get( Thread.currentThread() ); if (s==null) { // Aha -- we are the very first thread, the listener thread. // Start listening. try { // Set up the listen socket. ss = new ServerSocket( port ); System.out.println( "Listening on "+port ); while (true) { // Accept a new connection s = ss.accept(); synchronized( this ) { System.out.println( "Connection from "+s.getInetAddress() ); // Make a new thread to handle this connection Thread t = new Thread( this ); // Store the thread and socket in the lists sockets.addElement( s ); threads.addElement( t ); // The Socket object is "passed" to the new thread by // getting stuffed here. When the new thread is started, // it will pull the Socket object out of here based on // its own Thread object. handoff.put( t, s ); // All set! Start the thread! t.start(); } } } catch( IOException ie ) {} } else { // We are a processing socket. try { InputStream in = s.getInputStream(); OutputStream out = s.getOutputStream(); // Call the actually-do-something routine in the subclass of // this object, so that something can actually get done. process( in, out ); } catch( IOException ie ) { System.out.println( ie ); } } } }