import java.net.*; import java.io.*; import java.util.*; //******************************************************************// // A simple HTTP server // It's only capability is to pass back a requested file in the // server's directory or sub-directory. // Original code from Exploring Java by Patrick Niemeyer & Joshua Peck // 2nd Edition July 1997 O'Reilly // Modified by Eli Tilevich //******************************************************************// public class TinyHttpd { public static void main( String argv[] ) throws IOException { // Check that the port passed in the command line is valid int port = Integer.parseInt(argv[0]); if( port <= 1023 || port > 65535 ){ System.out.println("The port must be > 1023 and < 65536!"); System.exit(0); } // Now create a ServerSocket at the port ServerSocket ss = new ServerSocket( port ); // The server socket watches for a connection to this port // with its accept() method. When a connection occurs, it // returns a socket which is then passed to the TinyHttpdConnection // thread that will use it to handle the client. while ( true ) { // Because of the while( true) loop, this line will repeat // and wait for another accepted connection and will create // another TinyHttpdConnection thread to handle it. Thread serverThread = new Thread (new TinyHttpdConnection (ss.accept())); // Set the priority lower so that these client handlers // run at lower priority than the server. serverThread.setPriority ( Thread.NORM_PRIORITY - 1 ); // Start the thread - i.e. initiate a call to run() serverThread.start(); } } } // A thread class to handle the clients as they are accepted by // the ServerSocket in TinyHttpd class TinyHttpdConnection implements Runnable { Socket sock; // A socket is passed to the constructor. TinyHttpdConnection ( Socket sock ) { this.sock = sock; } // This thread run does the communication with the client // using the socket that was passed. public void run() { try { // Create an OutputStream into the socket OutputStream out = sock.getOutputStream(); //ET: to see how many threads are created System.out.println ("******* Starting a new thread # " + Thread.currentThread().getName()); // Similarly, get an InputStream from the socket, wrap it // in a DataInputStream so that we can use its readLine() // to read the request string from the socket. //String req = new DataInputStream( sock.getInputStream() ).readLine(); //ET: deprecated String req = new BufferedReader( new InputStreamReader (sock.getInputStream())).readLine(); // We can display to the console the request passed System.out.println( "Request: "+req ); // The request from a browser should be in the form: "GET /path/file.xyz" // So use a StringTokenizer to break the request string into // two substrings: "Get" and "/file.xyz" StringTokenizer st = new StringTokenizer( req ); // If there are not at least 2 substrings (tokens) and the first // one equal to "GET" then return an error. if ( (st.countTokens() >= 2) && st.nextToken().equals("GET") ) { // Get the next token, i.e. the file. // Check if it begins with "/" and strip it off if so // path is relative to the current directory if ( (req = st.nextToken()).startsWith("/") ){ req = req.substring( 1 ); } // If the last char is a slash then return the default // "index.html" as with standard web servers. if ( req.endsWith("/") || req.equals("") ){ req = req + "index.html"; } // Use the file name to read in the file from disk // into a byte array. Then write it to the OutputStream // we got from the socket. try { System.out.println("File= " + req); FileInputStream fis = new FileInputStream ( req ); byte [] data = new byte [ fis.available() ]; fis.read( data ); out.write( data ); } catch ( FileNotFoundException e ) { // Wrap a PrintStream around the socket OutputStream // to send an error message to the client new PrintStream( out ).println( "404 Object Not Found" ); } catch ( SecurityException e ) { new PrintStream( out ).println( "403 Forbidden" ); } } else { new PrintStream( out ).println( "400 Bad Request" ); } //disregard the rest of the request sock.close(); } catch ( IOException e ) { System.out.println( "I/O error " + e ); } } }