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_ThreadedListenServerHandleServer: Client 1HandleServer: Client 2etc.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 HandleServerComplete 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