Multi-Threaded Server

This server includes a minimum of three threads. The first runs the user interface. The second listens for client connections on a well-known port. When a connection is made, it starts an additional thread for each such connection and continues listening for in-coming connections. Thus, the thread structure is the following:

Server_Threaded
ListenServer
HandleServer: Client 1
HandleServer: Client 2
etc.

The discussion for each program will include two parts: first, the basic thread logic and, second, the complete code.

Skeleton

public class Server_Threaded extends Frame  {

    public void actionPerformed ( ActionEvent e )  {
    	Object s = e.getSource();
    	if ( s == listenButton )  {
	    listen = new ListenServer ( this );
	    listen.start ();
    	}  // end listenButton
    }  // end actionPerformed

}  // end Server_Threaded 
// ********************  ListenServer Class *******************
class ListenServer extends Thread  {

public void run  ()  {
        try  {
            listenSocket = new ServerSocket ( port );
            while ( true )  {
                Socket connection = listenSocket.accept();
                HandleServer handleServer = new HandleServer ( connection, source );
                handleServer.start ();
            }  // end while
    }  catch ( IOException e )  {
        System.exit ( 1 );
    }  // end catch
}  // end run

}  // end ListenServer 
// ********************  HandleServer Class *******************
class HandleServer extends Thread  {

public void run  ()  {
	try  {
                outStream = connection.getOutputStream ();
                outDataStream = new DataOutputStream ( outStream );
                inStream = connection.getInputStream ();
                inDataStream = new DataInputStream ( inStream );

                message = inDataStream.readUTF ();

		// *** process message  ***

                outDataStream.writeUTF ( message );

            }  // end try

            catch ( EOFException except ) {
            }  // end catch EOFException
            catch ( IOException e )  {
            }  // end catch IOException
}  // end run

}  // end HandleServer 

Complete Program

import java.awt.*;
import java.awt.event.*;
import java.net.*;
import java.io.*;
import java.util.*;

public class Server_Threaded extends Frame implements ActionListener, WindowListener {

//*****  Mulit-threaded server, accepts multiple messages
//       expected to be run on jbs.cs.unc.edu:8901


protected String DEFAULT_HOST = "jbspc.cs.unc.edu";
protected int DEFAULT_PORT = 8901;
String host;
int port;

ListenServer listen;

TextField hostDisplay, portDisplay;
TextArea logDisplay, msgDisplay;
Panel topPanel;
Panel middlePanel;
Panel buttonPanel;
Button listenButton, quitButton;


// **************  Server_Threaded

    public Server_Threaded ()  {

        super ( "Server_Threaded " );
        buildUI ();

    }  // end constructor


// **************  main

    public static void main ( String [ ] args )  {

        Server_Threaded server = new Server_Threaded ();

    }  // end main


//***********  Interface Methods   ***********


//****  ActionListener methods

  public void actionPerformed ( ActionEvent e )  {

    Object s = e.getSource();

    // *** process Button actions

    if ( s instanceof Button )  {

        if ( s == listenButton )  {
            listen = new ListenServer ( this );
            listen.start ();
        }  // end listenButton

        if ( s == quitButton )  {
            hide ();
            dispose ();
            System.exit ( 0 );
            }  // end quitButton

    }  // end process Button actions

  }  // end actionPerformed


//****  WindowListener methods

  public void windowActivated ( WindowEvent e )  {
  }

  public void windowDeactivated ( WindowEvent e )  {
  }

  public void windowOpened ( WindowEvent e )  {
  }

   public void windowClosed ( WindowEvent e )  {
  }

  public void windowClosing ( WindowEvent e )  {
    hide ();
    dispose ();
    System.exit(0);
  }

  public void windowIconified ( WindowEvent e )  {
  }

  public void windowDeiconified ( WindowEvent e )  {
  }


//***********  Utility Methods   ***********

// **************  buildUI

  private void buildUI ()  {

    try {
        InetAddress here = InetAddress.getLocalHost ();
        host = here.getHostName ();
    }
    catch (UnknownHostException e) { ;}

    hostDisplay = new TextField ( host, 30 );
    portDisplay = new TextField ( Integer.toString ( DEFAULT_PORT ), 4 );
    topPanel = new Panel ();
    topPanel.setLayout ( new GridLayout ( 2, 1 ) );
    topPanel.add ( hostDisplay );
    topPanel.add ( portDisplay );

    logDisplay = new TextArea ( 40, 10 );
    msgDisplay = new TextArea ( 40, 10 );
    middlePanel = new Panel ();
    middlePanel.setLayout ( new GridLayout ( 2, 1 ) );
    middlePanel.add ( logDisplay );
    middlePanel.add ( msgDisplay );

    listenButton = new Button ( "Listen" );
    quitButton = new Button ( "Quit" );
    listenButton.addActionListener ( this );
    quitButton.addActionListener ( this );
    buttonPanel = new Panel ( );
    buttonPanel.add ( listenButton );
    buttonPanel.add ( quitButton );

    add ( "North", topPanel );
    add ( "Center", middlePanel );
    add ( "South", buttonPanel );

    resize ( 400, 450 );
    show ();

    }  // end buildUI


}  // end Server_Threaded

 

/********************************  ListenServer

 

class ListenServer extends Thread  {

Server_Threaded source;
ServerSocket listenSocket;
int port;
Socket connection;
HandleServer handle;
boolean again = true;


// **************  Server_Threaded

    ListenServer ( Server_Threaded s)  {

        super ();

        source = s;

    }  // end constructor


// **************  run

    public void run  ()  {

        if ( ! ( source.portDisplay.getText () ).equals ( "" ) ) port = Integer.parseInt ( source.portDisplay.getText () );
        else port = source.DEFAULT_PORT;

        try  {

            listenSocket = new ServerSocket ( port );
            source.logDisplay.setText ( "Server started:\n  listening on port " + port + "\n\n" );

            while ( true )  {

                Socket connection = listenSocket.accept();
                HandleServer handleServer = new HandleServer ( connection, source );
                handleServer.start ();

            }  // end while

    }  catch ( IOException e )  {
        e.printStackTrace ();
        source.logDisplay.setText ( "Error is opening ServerSocket\n" );
        System.exit ( 1 );
    }  // end catch


}  // end run


}  // end ListenServer

 

/********************************  HandleServer

 

class HandleServer extends Thread  {

Server_Threaded source;
Socket connection;

InputStream inStream;
DataInputStream inDataStream;
OutputStream outStream;
DataOutputStream outDataStream;

String message;


// **************  HandleServer

    HandleServer ( Socket socket, Server_Threaded s)  {

        super ();
        connection =  socket;
        source =  s;

    }  // end constructor


// **************  run

    public void run  ()  {

        String stringIn, stringOut;
        boolean again = true;

        InetAddress inet = connection.getInetAddress ();
        String origin = inet.getHostName ();
        int originport = connection.getPort ();

        source.logDisplay.appendText ( "Adding Client: \n  "+origin+":"+originport+"\n\n" );


        try  {

            outStream = connection.getOutputStream ();
            outDataStream = new DataOutputStream ( outStream );
            inStream = connection.getInputStream ();
            inDataStream = new DataInputStream ( inStream );

            while ( true )  {

                message = inDataStream.readUTF ();
                source.logDisplay.appendText ( "  Message, below, received\n" );
                source.msgDisplay.setForeground ( Color.red );
                source.msgDisplay.setText ( message );

                outDataStream.writeUTF ( message );
                source.logDisplay.appendText ( "  Message returned to client \n\n" );

            }  // end while

        }  // end try

        catch ( EOFException except ) {
            source.logDisplay.appendText ( "  Connection closed by Client\n\n" );
            try  {
                connection.close ();
                return;
            }
            catch ( IOException e )  {
                e.printStackTrace ();
                return;
            }  // end IOException

         }  // end catch EOFException
         catch ( IOException e )  {
            source.logDisplay.appendText ( "  Connection closed abormally\n" );
            e.printStackTrace ();
            return;
         }  // end catch IOException

    }  // end run


}  // end HandleServer