import java.net.*; import java.io.*; /** A multithreaded variation of EchoServer. * * Taken from Core Web Programming from * Prentice Hall and Sun Microsystems Press, * . * © 2001 Marty Hall and Larry Brown; * may be freely used or adapted. */ public class ThreadedEchoServer extends EchoServer implements Runnable { public static void main(String[] args) { int port = 8088; if (args.length > 0) { try { port = Integer.parseInt(args[0]); } catch(NumberFormatException nfe) {} } ThreadedEchoServer echoServer = new ThreadedEchoServer(port, 0); echoServer.serverName = "Threaded EchoServer"; } public ThreadedEchoServer(int port, int connections) { super(port, connections); } /** The new version of handleConnection starts a thread. This * new thread will call back to the old version of * handleConnection, resulting in the same server behavior * in a multithreaded version. The thread stores the Socket * instance since run doesn't take any arguments, and since * storing the socket in an instance variable risks having * it overwritten if the next thread starts before the run * method gets a chance to copy the socket reference. */ public void handleConnection(Socket server) { Connection connectionThread = new Connection(this, server); connectionThread.start(); } public void run() { Connection currentThread = (Connection)Thread.currentThread(); try { super.handleConnection(currentThread.getSocket()); } catch(IOException ioe) { System.out.println("IOException: " + ioe); ioe.printStackTrace(); } } } /** This is just a Thread with a field to store a Socket object. * Used as a thread-safe means to pass the Socket from * handleConnection to run. */ class Connection extends Thread { private Socket serverSocket; public Connection(Runnable serverObject, Socket serverSocket) { super(serverObject); this.serverSocket = serverSocket; } public Socket getSocket() { return serverSocket; } } EchoServer.java Creates a Web page showing all data sent from the client (browser). import java.net.*; import java.io.*; import java.util.StringTokenizer; /** A simple HTTP server that generates a Web page showing all * of the data that it received from the Web client (usually * a browser). To use this server, start it on the system of * your choice, supplying a port number if you want something * other than port 8088. Call this system server.com. Next, * start a Web browser on the same or a different system, and * connect to http://server.com:8088/whatever. The resultant * Web page will show the data that your browser sent. For * debugging in servlet or CGI programming, specify * http://server.com:8088/whatever as the ACTION of your HTML * form. You can send GET or POST data; either way, the * resultant page will show what your browser sent. * * Taken from Core Web Programming from * Prentice Hall and Sun Microsystems Press, * © 2001 Marty Hall and Larry Brown; * may be freely used or adapted. */ public class EchoServer extends NetworkServer { protected int maxRequestLines = 50; protected String serverName = "EchoServer"; /** Supply a port number as a command-line * argument. Otherwise, use port 8088. */ public static void main(String[] args) { int port = 8088; if (args.length > 0) { try { port = Integer.parseInt(args[0]); } catch(NumberFormatException nfe) {} } new EchoServer(port, 0); } public EchoServer(int port, int maxConnections) { super(port, maxConnections); listen(); } /** Overrides the NetworkServer handleConnection method to * read each line of data received, save it into an array * of strings, then send it back embedded inside a PRE * element in an HTML page. */ public void handleConnection(Socket server) throws IOException{ System.out.println (serverName + ": got connection from " + server.getInetAddress().getHostName()); BufferedReader in = SocketUtil.getReader(server); PrintWriter out = SocketUtil.getWriter(server); String[] inputLines = new String[maxRequestLines]; int i; for (i=0; i\n" + "\n" + "\n" + " \n" + "\n" + "\n" + "\n" + " " + serverName + " Results \n" + "Here is the request line and request headers\n" + "sent by your browser:\n" + " "); } // Print bottom of a standard Web page. private void printTrailer(PrintWriter out) { out.println (" \n" + "\n" + "\n"); } // Normal Web page requests use GET, so this server can simply // read a line at a time. However, HTML forms can also use // POST, in which case we have to determine the number of POST // bytes that are sent so we know how much extra data to read // after the standard HTTP headers. private boolean usingPost(String[] inputs) { return(inputs[0].toUpperCase().startsWith("POST")); } private void readPostData(String[] inputs, int i, BufferedReader in) throws IOException { int contentLength = contentLength(inputs); char[] postData = new char[contentLength]; in.read(postData, 0, contentLength); inputs[++i] = new String(postData, 0, contentLength); } // Given a line that starts with Content-Length, // this returns the integer value specified. private int contentLength(String[] inputs) { String input; for (int i=0; iOverride this method in servers * you write. * * This generic version simply reports the host that made * the connection, shows the first line the client sent, * and sends a single line in response. */ protected void handleConnection(Socket server) throws IOException{ BufferedReader in = SocketUtil.getReader(server); PrintWriter out = SocketUtil.getWriter(server); System.out.println ("Generic Network Server: got connection from " + server.getInetAddress().getHostName() + "\n" + "with first line '" + in.readLine() + "'"); out.println("Generic Network Server"); server.close(); } /** Gets the max connections server will handle before * exiting. A value of 0 indicates that server should run * until explicitly killed. */ public int getMaxConnections() { return(maxConnections); } /** Sets max connections. A value of 0 indicates that server * should run indefinitely (until explicitly killed). */ public void setMaxConnections(int maxConnections) { this.maxConnections = maxConnections; } /** Gets port on which server is listening. */ public int getPort() { return(port); } /** Sets port. You can only do before "connect" is * called. That usually happens in the constructor. */ protected void setPort(int port) { this.port = port; } } SocketUtil.java Simplifies the creation of a PrintWriter and BufferedReader. import java.net.*; import java.io.*; /** A shorthand way to create BufferedReaders and * PrintWriters associated with a Socket. * * Taken from Core Web Programming from * Prentice Hall and Sun Microsystems Press, * © 2001 Marty Hall and Larry Brown; * may be freely used or adapted. */ public class SocketUtil { /** Make a BufferedReader to get incoming data. */ public static BufferedReader getReader(Socket s) throws IOException { return(new BufferedReader( new InputStreamReader(s.getInputStream()))); } /** Make a PrintWriter to send outgoing data. * This PrintWriter will automatically flush stream * when println is called. */ public static PrintWriter getWriter(Socket s) throws IOException { // Second argument of true means autoflush. return(new PrintWriter(s.getOutputStream(), true)); } }
ThreadedEchoServer.java A multithreaded version of EchoServer, where each client request is serviced on a separate thread. Requires the following classes
Permanent link to this article: http://bangla.sitestree.com/threadedechoserver-java-a-multithreaded-version-of-echoserver-where-each-client-request-is-serviced-on-a-separate-thread-requires-the-following-classes/