Home : Course Map : Chapter 14 :
Thread Workers for Clients
JavaTech
Course Map
Chapter 14

Web Servers
Design of Server
ServerSocket
Threads For Clients
Client Streams
HTTP Protocol
Run Server
  Demo 1
Secure Server
  Demo 2
More Security
A client application
  Demo 3
Server Apps
Servlets
Exercises

     About JavaTech
     Codes List
     Exercises
     Feedback
     References
     Resources
     Tips
     Topic Index
     Course Guide
     What's New

After a client is connected to a Socket, we create an instance of our subclass of Thread called Worker to handle the client. We set the priority lower on our thread so that the client processing does not dominate other tasks such as the ServerSocket monitoring of new incoming clients and the serving of other clients by other Worker objects.

import java.net.*;
import java.io.*;
import java.util.*;

/** Threaded process to serve the client connected to the socket.**/
class Worker extends Thread {

  Socket fClient = null;

  /** Pass the socket as a argument to the constructor **/
  Worker ( Socket client ) throws SocketException {
    fClient = client;

    // Set the thread priority down so that the ServerSocket
    // will be responsive to new clients.
    setPriority ( NORM_PRIORITY - 1 );
  } // ctor

  /**
    *  This thread receives a message from the client that will
    *  request a web page file. The file name is found relative to
    *  the directory location of this code.
   **/
  public void run () {
    try {
      // Use the client socket to obtain an input stream from it.
      InputStream socket_in = fClient.getInputStream ();
      // For text input we wrap an InputStreamReader around
      // the raw input stream and set ASCII character encoding.
      InputStreamReader isr =
         new InputStreamReader (socket_in, "8859_1");
      // Finally, use a BufferReader wrapper to obtain
      // buffering and higher order read methods.
      BufferedReader client_in = new BufferedReader (isr);

      // Now get an output stream to the client.
      OutputStream client_out = fClient.getOutputStream ();

      // For text output we wrap an OutputStreamWriter around
      // the raw output stream and set ASCII character encoding.
      OutputStreamWriter osr =
        new OutputStreamWriter (client_out, "8859_1");
      // Finally, we use a PrintWriter wrapper to obtain its
      // higher level output methods.Open in autoflush mode.
      // (Autoflush occurs only with println() method.)
      PrintWriter pw_client_out = new PrintWriter (osr, true );

      // First read the message from the client
      String client_str = client_in.readLine ();
      System.out.println ("Client message: "+client_str);

      // Split the message into substrings.
      String [] tokens = client_str.split(" ");

      // Check that the message has a minimun number of words
      // and that the first word is the GET command.
      if ((tokens.length >= 2) &&
           tokens[0].equals ("GET")) {
         String file_name = tokens[1];

        // Ignore the leading "/" on the file name.
        if (file_name.startsWith ("/"))
            file_name = file_name.substring (1);

        // If no file name is there, use index.html default.
        if (file_name.endsWith ("/") || file_name.equals (""))
           file_name = file_name + "index.html";

        // Check if the file is hypertext or plain text
        String content_type;
        if (file_name.endsWith (".html") ||
            file_name.endsWith (".htm")) {
           content_type = "text/html";
        }
        else {
          content_type = "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.
          FileInputStream file_in = new FileInputStream  (file_name);

          // Send the header.
          pw_client_out.print ("HTTP/1.0 200 OK\r\n");
          File file = new File (file_name);
          Date date = new Date (file.lastModified ());
          pw_client_out.print ("Date: " + date + "\r\n");
          pw_client_out.print ("Server: MicroServer 1.0\r\n");
          pw_client_out.print ("Content-length: " + file_in.available ()
            + "\r\n");
          pw_client_out.print ("Content-type: " + content_type
            + "\r\n\r\n");

          // Creat a byte array to hold the file.
          byte [] data = new byte [file_in.available ()];

          file_in.read (data);     // Read file into the byte array
          client_out.write (data); // Write it to client output stream
          client_out.flush ();     // Remember to flush output buffer
          file_in.close ();        // Close file input stream

        } catch (FileNotFoundException e) {
          // If no such file, then send the famous 404 message.
          pw_client_out.println ("404 Object Not Found" );
        }
      } else{
        pw_client_out.println ("400 Bad Request");
      }
    } catch (IOException e) {
      System.out.println ( "I/O error " + e );
    }

    // Close client socket.
    try {
      fClient.close ();
    } catch (IOException e){
      System.out.println ("I/O error " + e );
    }
    // On return from run () the thread process will stop.
  } // run

} // class Worker

 

A Worker constructor is passed the Socket object. The run() method is, of course, the heart of the thread and is where the interaction with the client occurs. Before we discuss possible tasks for the Worker, we look on the next page at setting up I/O streams with the client.

References & Web Resources

Latest update: Dec. 9, 2004
  
  Part I Part II Part III
Java Core 1  2  3  4  5  6  7  8  9  10  11  12 13 14 15 16 17
18 19 20
21
22 23 24
Supplements

1  2  3  4  5  6  7  8  9  10  11  12

Tech 1  2  3  4  5  6  7  8  9  10  11  12
Physics 1  2  3  4  5  6  7  8  9  10  11  12

Java is a trademark of Sun Microsystems, Inc.