Banner

Michael Chungkun Chen

SeasNet ID = mchen

Course CS 118

Project 1 [WebServer.java]


The source code following is of part A and B combined, using the fixed width font Verdana.  The modifications that I made from the original code given to us by the packet is marked in bold face font.

 

<<BEGIN SOURCE WebServer.java>>

import java.io.* ;

import java.net.* ;

import java.util.* ;

 

public final class WebServer

{

    public static void main(String argv[]) throws Exception

    {

       ServerSocket mysock = null;

       Socket clientSocket = null;

       // Set the port number.

       int port = 65534;

 

       // Establish the listen socket.

       try {

       mysock = new ServerSocket(port);

       } catch (IOException e) {

              System.out.println("Could not listen on port: " + port);

              System.exit(-1);

       }

      

       // Process HTTP service requests in an infinite loop.

       while (true) {

              // Listen for a TCP connection request.

              try {

                     clientSocket = mysock.accept();

                     System.out.println("Connection made on port: " + port);

              } catch (IOException e) {

                     System.out.println("Accept failed: ");

                     System.exit(-1);

              }

 

              // Construct an object to process the HTTP request message.

              HttpRequest request = new HttpRequest( clientSocket );

             

              // Create a new thread to process the request.

              Thread thread = new Thread(request);

              // Start the thread.

              thread.start();

       }

    }

}

 

final class HttpRequest implements Runnable

{

       final static String CRLF = "\r\n";

       Socket socket;

 

       // Constructor

       public HttpRequest(Socket socket) throws Exception

       {

              this.socket = socket;

       }

 

       // Implement the run() method of the Runnable interface.

       public void run()

       {

              try {

                     processRequest();

              } catch (Exception e) {

                     System.out.println(e);

              }

       }

 

       private void processRequest() throws Exception

       {

              // Get a reference to the socket's input and output streams.

              InputStream is = socket.getInputStream();

              DataOutputStream os = new DataOutputStream(socket.getOutputStream());

 

              // Set up input stream filters.

              BufferedReader br =  new BufferedReader( new InputStreamReader(is));

                    

              // Get the request line of the HTTP request message.

              String requestLine = br.readLine();

 

              System.out.println();

              System.out.println(requestLine);

 

              // Get and display the header lines.

              String headerLine = null;

              while ((headerLine = br.readLine()).length() != 0) {

                     System.out.println(headerLine);

              }

 

//Beginning of part B

 

              // Extract the filename from the request line.

              StringTokenizer tokens = new StringTokenizer(requestLine);

              tokens.nextToken();  // skip over the method, which should be "GET"

              String fileName = tokens.nextToken();

 

              // Prepend a "." so that file request is within the current directory.

              fileName = "." + fileName;

 

              // Open the requested file.

              FileInputStream fis = null;

              boolean fileExists = true;

              try {

                     fis = new FileInputStream(fileName);

              } catch (FileNotFoundException e) {

                     fileExists = false;

              }

 

              // Construct the response message.

              String statusLine = null;

              String contentTypeLine = null;

              String entityBody = null;

              if (fileExists) {

                     statusLine = "HTTP/1.0 200 OK" + CRLF;

                     contentTypeLine = "Content-type: " + contentType( fileName ) + CRLF;

              } else {

                     statusLine = "HTTP/1.0 404 Not Found" + CRLF;

                     contentTypeLine = "Content-type: text/html" + CRLF;

                     entityBody = "<HTML>" + CRLF +

                     "<HEAD><TITLE>Not Found</TITLE></HEAD>" + CRLF +

                     "<BODY>Not Found<


Home | About Me | Text Depository | Future Enhancements | Guest Book | Links

Copyright © 1998-2008 Michael Chungkun Chen
All Rights Reserved.

/BODY></HTML>";

              }

 

              // Send the status line.

              os.writeBytes(statusLine);

 

              // Send the content type line.

              os.writeBytes(contentTypeLine);

 

              // Send a blank line to indicate the end of the header lines.

              os.writeBytes(CRLF);

 

              // Send the entity body.

              if (fileExists) {

                     sendBytes(fis, os);

                     fis.close();

              } else {

                     os.writeBytes(entityBody);

              }

 

 

              // Close streams and socket.

              os.close();

              br.close();

              socket.close();

              System.out.println("Connection closed.");

       }

 

       private static void sendBytes(FileInputStream fis, OutputStream os) throws Exception

       {

              // Construct a 1K buffer to hold bytes on their way to the socket.

              byte[] buffer = new byte[1024];

              int bytes = 0;

              // Copy requested file into the socket's output stream.

              while((bytes = fis.read(buffer)) != -1 ) {

                     os.write(buffer, 0, bytes);

              }

       }

 

       private static String contentType(String fileName)

       {

              if(fileName.endsWith(".htm") || fileName.endsWith(".html")) {

                     return "text/html";

              }

              if(fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {

                     return "image/jpeg";

              }

              if(fileName.endsWith(".gif")) {

                     return "image/gif";

              }

 

//Following lines include the five extra mime extensions.

              if(fileName.endsWith(".txt") || fileName.endsWith(".text")) {

                     return "text/plain";

              }

              if(fileName.endsWith(".au")) {

                     return "audio/basic";

              }

              if(fileName.endsWith(".mpg") || fileName.endsWith(".mpeg")) {

                     return "video/mpeg";

              }

              if(fileName.endsWith(".avi")) {

                     return "video/avi";

              }

              if(fileName.endsWith(".ps")) {

                     return "application/PostScript";

              }

              return "application/octet-stream";

       }

      

}

 

<<END SOURCE WebServer.java>>


The following excerpt is copied from the java class WebServer after a request was made by Microsoft’s Internet Explorer version 5.5 on a SeasNet machine, the request line is http://olvera:65534/ in this case the server applet was run from the olvera machine and the applet uses the port specified as 65534.

 

Connection made on port: 65534

[This line was generated by the applet which I added to inform the server console that a connection was made on the specified port]

 

GET / HTTP/1.0

[The specification of RFC 1945 states that there are 4 primary commands, GET, HEAD, POST, and extension-method.  In this situation we used the GET command.  The following fowardslash signifies that the file that we wish to get, the WebServer will interpret this to mean the directory the WebServer applet was run from.  The next part HTTP signifies the protocol being used, and the number following the / is the version(1.0) of the HTTP protocol that is implemented by the client.]

Accept: application/vnd.ms-excel, application/msword, application/vnd.ms-powerpoint, image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-comet, */*

[The accept request-header field is used to indicate a list of media ranges which are acceptable as a response to the request, a * indicates all, so a */* indicates all types and subtypes are accepted, while a type/* indicates all subtypes of type type is accepted]

Accept-Language: en-us

[This field is similar to accept except that it indicates which set of natural languages are preferred in the response to the client.  In our case it is English-us]

User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0)

[This field contains information about the user agent and version number originating the request.  This is for statistical purposes, the tracing of protocol violations, the automated recognition of user agents for the sake of tailoring responses to avoid particular user agent limitations.  The items in parenthesis provide more details about the user agent.]

Host: olvera:65534

[This field simply states the host name and the port number the format of this field should be as follows Hostname[:portnumber] where the port number is optional]

Connection: Keep-Alive

[This field does not appear in RFC 1945.  The client is trying to request a persistent connection with the server in which the connection remains open after the message is sent.]

Connection closed.

[This line was also generated by the applet, also added by me, in order to inform the server console the connection was closed.]