Title: Networking: A Better Server Model
Course: CPS 261: Advanced Java Concepts ~ DL & MM MASTER

Networking: A Better Server Model

We need a more functional Server that has a better structure. Here are the things we will accomplish:

1. We want the server to run in a thread that is not the main thread.
2. We want the main thread to have a way to terminate the server.
3. We want the Server to pass off the actual connection to another thread to allow the Server to immediately go back to the accept call.
4. We would like to make use of most of this code by extending EchoServer so that we can reuse this code for many protocol handlers.

MotherServer.java


import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

public class MotherServer implements Runnable {

    ServerSocket serverSocket = null;
    int portNum=-1;
    EchoServer echoServer= null;
    boolean continueListening = true;
    Thread myThread = null;

    boolean startServer(int portNum, EchoServer echoServer)
    {
        this.portNum = portNum;
        try {
            serverSocket = new ServerSocket(portNum);
        } catch (IOException e) {
            System.out.println("ServerSocket connect error: " + e);
            return false;
        }
        this.echoServer = echoServer;
        myThread = new Thread(this);
        myThread.start();
        return true;
    }

    public void run() // This is where the Server executes
    {
        continueListening = true;
        while(continueListening)
        {
            try {
                Socket sock = serverSocket.accept();
                echoServer.handleConnect(sock);
            } catch (IOException e) {
                System.out.println("ServerSocket accept error: " + e);
                continueListening = false;
            }
        }
        System.out.println("MyServer run thread exitting");
    }

    public void stopServer()
    {
        continueListening = false;
        try {
            serverSocket.close();
        } catch (IOException e) {
            System.out.println("stopServer error: " + e);
        }
    }

    static String getHostInfo()
    {
        String retStr="";
        try {
            InetAddress iaddr = InetAddress.getLocalHost();
            retStr= String.format("Host:%s ipaddr=%s",
                    iaddr.getHostName(), iaddr.getHostAddress());
        }
        catch (UnknownHostException e) {
            retStr = e.toString();
        }

        return retStr;
    }
}



EchoServer.java


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;

public class EchoServer implements  Runnable, Cloneable{

    Socket clientSocket=null;
    Thread myThread = null;




    public void handleConnect(Socket s) {

        clientSocket = s;

        // Something very unique is happening here.
        // We want each connection to run on its own object
        // However we don't want to call the EchoServer constructor to get this.
        // We want this class to be the base of many other protocol handler classes.
        // By calling clone, we will make an instance that has the characteristics of the
        // derived class instead of the EchoServer.


        try {
            Runnable protocol_handler = (Runnable)clone();

            Thread myThread = new Thread(protocol_handler);
            System.out.println("Launching a new Child Thread");
            myThread.start();
        }
        catch (CloneNotSupportedException e) {
            System.out.println("EchoServer.handleConnect Clone error: "+e);
        }
    }
    public void run()
    {
        InputStream is=null;
        OutputStream os=null;
        try {
            is = clientSocket.getInputStream();
            os = clientSocket.getOutputStream();

            processStream(is, os);

        }
        catch (IOException e) {
            System.out.println("Echo Server Exception: "+e);
        }
        finally
        {
            try
            {
                if (is != null) is.close();
                if (os != null) os.close();
            }
            catch (IOException e)
            {
                System.out.println("run:  Stupid exception that shouldn't happen");
            }
        }
        System.out.println("Exitting Child Server Thread");
    }
    public void processStream(InputStream is, OutputStream os)
    {
        System.out.println("EchoServer.processStream begins");
        Scanner input = new Scanner(is);
        PrintStream ps = new PrintStream(os);

        while (input.hasNextLine())
        {
            processNextLine(input, ps);
        }
        input.close();
        ps.close();
        System.out.println("Exitting processStream");
    }
    public void processNextLine(Scanner input, PrintStream ps)
    {
        String s= input.nextLine();
        ps.println(s);
        System.out.println("EchoServer echoed: "+s);
    }

    public void monitorServer()
    {
        MotherServer myServer = new MotherServer();
        System.out.println(MotherServer.getHostInfo());
        myServer.startServer(4444, this);

        Scanner keyboard = new Scanner(System.in);
        String s="";
        while (!s.equals("quit"))
        {
            System.out.println("Whenever you want to stop the server, enter \"quit\" ");
            s = keyboard.next();
        }
        keyboard.close();
        myServer.stopServer();
    }
    public static void main(String[] args) {

        EchoServer es = new EchoServer();
        es.monitorServer();
        System.out.println("Exitting EchoServer");

    }



}



Last Modified: September 6, 2015 10:55 PM