import java.net.*;
import java.io.*;

        // A simple server that accepts a client connection
        // and sends back the length of the strings it
        // receives from the client.

        // Multiple clients are handled consecutively.
        // This version differs from LineLengthServer in that
        // the service functionality is devolved from the listener
        // to the separate class LineLengthResponder, which is
        // a subclass of TCPEndpoint.
class MultiLineLengthServer {
    public MultiLineLengthServer(int port) throws Exception {
        try{
            // Listen on port.
            serverSocket = new ServerSocket(port);
        }
        catch(BindException e){
            throw new Exception("Failed to create a server socket: "+
                                e.getMessage());
        }
    }

        // Read strings and return their length (as a String)
        // to the client.
    public void run() throws Exception {
        ServerSocket serverSocket = getServerSocket();
        // Wait up to 30 seconds for clients.
        final int timeToWait = 30000;
        boolean keepWaiting = true;

        while(keepWaiting){
            Socket clientSocket = null;
            try{
                // Wait for a client to make contact.
                System.out.println("Listening for a client on port: "+
                            serverSocket.getLocalPort());
                // Set how long we are prepared to wait.
                serverSocket.setSoTimeout(timeToWait);
                clientSocket = serverSocket.accept();

                // Contact ...
                System.out.println("A client has arrived.");
                // Devolve action to a separate object.
                LineLengthResponder responder =
                                new LineLengthResponder(clientSocket);
                responder.run();
                // Client has finished.
            }
            catch(InterruptedIOException e){
                // We timed out waiting for a client.
                keepWaiting = false;
                System.out.println("No more clients after: "+
                                   timeToWait/1000+" seconds.");
            }
            finally{
                if(clientSocket != null){
                    System.out.println("The client has gone.");
                }
            }
        }
        // No more clients, so close the socket.
        serverSocket.close();
    }

        // Read lines and return their length until the
        // client terminates.
    protected class LineLengthResponder extends TCPEndpoint {
        public LineLengthResponder(Socket socket) throws Exception {
            super(socket);
        }

        public void run(){
            try{
                String request = getLine();
                while(request != null){
                    // Write the length of the line as a String.
                    sendLine(String.valueOf(request.length()));
                    request = getLine();
                }
            }
            catch(IOException e){
                System.err.println("IOException talking to the client: "+
                            e.getMessage());
            }
            // Close the socket to the client.
            close();
        }
    }
    protected ServerSocket getServerSocket(){
        return serverSocket;
    }

    // The socket on which the listening is done.
    private final ServerSocket serverSocket;
}
