A Multithreaded Server Framework The operation of most servers involves listening for connections, accepting connections, processing requests received over the connections, and terminating connections after all requests have been processed. The handling of multiple connections is generally performed using multiple threads. As such, a general framework for multithreaded servers can be developed. Listing 32.1 provides such a framework for a generic server named GenericServer. Appendix A, "Java Language Summary," summarizes how multithreading is accomplished in Java. The GenericServer class is the main class of the program. It defines serverPort as the number of the port that the server is to listen on. You would change 1234 to the well-known port of the service that the server is to implement. The main() method creates an instance of GenericServer and invokes the instance's run() method. The run() method creates a new ServerSocket and assigns the socket to the server variable. It then executes an infinite loop where it listens for an incoming connection and creates a Socket instance to service the connection. The Socket instance is assigned to the client variable. A new ServerThread object is created to process client requests and the start() method of this object is invoked to get the thread up and running. The ServerThread class extends the Thread class. It declares the client field variable to keep track of the client socket. Its run() method creates objects of class ServiceInputStream and ServiceOutputStream to communicate with the client. These streams are buffered to enhance I/O performance. A while statement is used to repeatedly invoke the processRequest() method to process client requests. If processRequest() returns a value of false, the service is completed, the while loop ends, and the client socket is closed. The processRequest() method is a stub for implementing service-specific request processing. The ServiceInputStream, ServiceOutputStream, and ServiceRequest classes are placeholders for implementing client I/O and request processing. NOTE: GenericServer handles exceptions by exiting. In real server implementations this may not be the best response. To implement a real server based on GenericServer, you should substitute your own exception handling code. LISTING 32.1. THE GenericServer CODE. import java.net.*; import java.io.*; import java.util.*; public class GenericServer { // Replace 1234 with the well-known port used by the server. int serverPort = 1234; public static void main(String args[]){ // Create a server object and run it GenericServer server = new GenericServer(); server.run(); } public GenericServer() { super(); } public void run() { try { // Create a server socket on the specified port ServerSocket server = new ServerSocket(serverPort); do { // Loop to accept incoming connections Socket client = server.accept(); // Create a new thread to handle each connection (new ServerThread(client)).start(); } while(true); } catch(IOException ex) { System.exit(0); } } } class ServerThread extends Thread { Socket client; // Store a reference to the socket to which the client is connected public ServerThread(Socket client) { this.client = client; } // Thread's entry point public void run() { try { // Create streams for communicating with client ServiceOutputStream outStream = new ServiceOutputStream( new BufferedOutputStream(client.getOutputStream())); ServiceInputStream inStream = new ServiceInputStream(client.getInputStream()); // Read client's request from input stream ServiceRequest request = inStream.getRequest(); // Process client's request and send output back to client while (processRequest(outStream)) {}; }catch(IOException ex) { System.exit(0); } try { client.close(); }catch(IOException ex) { System.exit(0); } } // Stub for request processing public boolean processRequest(ServiceOutputStream outStream) { return false; } } // Input stream filter class ServiceInputStream extends FilterInputStream { public ServiceInputStream(InputStream in) { super(in); } // Method for reading client requests from input stream public ServiceRequest getRequest() throws IOException { ServiceRequest request = new ServiceRequest(); return request; } } // Output stream filter class ServiceOutputStream extends FilterOutputStream { public ServiceOutputStream(OutputStream out) { super(out); } } // Class to implement client requests class ServiceRequest { }