import java.net.*; import java.io.*; import java.util.*; public class TinyHttpd { public static void main( String argv[] ) throws IOException { // Get the port number from the command line // Create a ServerSocket object to watch // this port for clients ServerSocket ss = new ServerSocket( Integer.parseInt(argv[0])); System.out.println("starting..."); // Here we loop indefinitely, just waiting for // clients to connect while ( true ) { // accept() does not return until a client // requests a connection. // Now that a client has arrived, create an instance // of our special thread subclass to respond to it. new TinyHttpdConnection( ss.accept() ).start(); System.out.println("new connection"); } // Now loop back around and wait // for next client to be accepted. } } // Here is our thread class to handle clients. class TinyHttpdConnection extends Thread { Socket client; // Pass the socket as a argument to the constructor TinyHttpdConnection ( Socket client ) throws SocketException { this.client = client; // Set the thread priority down so that the ServerSocket // will be responsive to new clients. setPriority( NORM_PRIORITY - 1 ); } public void run() { try { // Use the client socket to obtain an input stream from it. // For text input we wrap an InputStreamReader around // the raw input stream and set ASCII character encoding. // Finally, use a BufferReader wrapper to obtain // buffering and higher order read methods. BufferedReader in = new BufferedReader( new InputStreamReader(client.getInputStream(),"8859_1")); // Now get an output stream to the client. OutputStream out = client.getOutputStream(); // For text output we wrap an OutputStreamWriter around // the raw output stream and set ASCII character encoding. // Finally, we use a PrintWriter wrapper to obtain its // higher level output methods. // Open in append mode. PrintWriter pout = new PrintWriter( new OutputStreamWriter(out, "8859_1"), true ); // First read the request line from the client String request = in.readLine(); System.out.println( "Request: "+request ); // Use aStringTokenizer to examine the request text. StringTokenizer st = new StringTokenizer( request ); // Check if HTTP/1.0 or later. If so, add MIME header boolean sendMIME = false; if ( request.indexOf("HTTP/") != -1) sendMIME = true; // Check that the request has a minimun number of words // and that the first word is the GET command. if ( (st.countTokens() >= 2) && st.nextToken().equals("GET") ) { // Ignore the leading "/" on the file name. if ( (request = st.nextToken()).startsWith("/") ) request = request.substring( 1 ); // If no file name is there, use index.html default. if ( request.endsWith("/") || request.equals("") ) request = request + "index.html"; // Check if the file is hypertext or plain text String ContentType; if (request.endsWith(".html") || request.endsWith(".htm")) { ContentType = "text/html"; } else { ContentType = "text/plain"; } // Now read the file from the disk and write it to the // output stream to the client. try { // Open a stream to the file. Remember that by this // all the text but the file name has been stripped // from the "request" string. FileInputStream fis = new FileInputStream ( request ); if( sendMIME) { // Follow example in "Java Network Programming" PrintStream os = new PrintStream(out); os.print("HTTP/1.0 200 OK\r\n"); Date now = new Date(); os.print("Date: " + now + "\r\n"); os.print("Server: TinyHttpd 1.0\r\n"); os.print("Content-length: " + fis.available() + "\r\n"); os.print("Content-type: " + ContentType + "\r\n\r\n"); } // Creat a byte array to hold the file. byte [] data = new byte [ fis.available() ]; fis.read( data ); // Read file into the byte array out.write( data );// Write it to client output stream out.flush(); // Remember to flush output buffer } catch ( FileNotFoundException e ) { // If no such file, then send the famous 404 message. pout.println( "404 Object Not Found" ); } } else pout.println( "400 Bad Request" ); client.close(); } catch ( IOException e ) { System.out.println( "I/O error " + e ); } // On return from run() the thread process will stop. } }