CSE 410 22wi Homework 8
Threads

Out: Sunday, 6 March
Due: Sunday, 13 March, 11:59 pm
Latest Possible Submission Time: Tuesday, 15 March, 11:59 pm
Turnin: Gradescope

Overview

You start with code that implements a simple form of web server, written as a single threaded Java program. The web server is very restrictive:

You should convert the implementation to one using multiple threads, so that requests can be handled in any order.

Operation of the Server

Clients send requests to the server, and receive responses from it, using "sockets." Sockets are network communication endpoints. The server uses two sockets. All requests arriving on one of them are provided DocA, and all requests on the other are provided DocB. (This simplifies the implementation, which never bothers to look at what was sent as the request, since it can be for only one thing.) The accept() call on the server's serversocket returns when a client connects, which is how the server knows that a request has been sent.

The code is divided into HTTPServer and HTTPSocket classes. The HTTPServer is the main control flow. It creates two HTTPSockets and then goes into a loop. During each iteration of the loop, first a method of the DocA socket, then a method of the DocB socket, is invoked to handle an incoming request, then the user is asked to indicate whether or not to terminate the server. We might draw this control flow like this:

You allow arbitrary order of requests by multi-threading the implementation. One thread is dedicated to handling requests on the DocA socket, another thread handles requests on the DocB socket, and the final thread handles user input regarding termination. Because the process starts with a thread (called the main thread), you need to create only two additional threads. The main thread is used to handle user input and server termination. Multithreaded execution might be drawn like this (where dashed lines are thread creation and solid lines are normal control flow):

You should be careful to handle possible race conditions when you multi-thread. The application has been chosen in part because it is naturally free of race conditions, but one has been introduced specifically for the purpose of this homework.

A Detail

Network communication endpoints use sockets. A socket "is bound to" (is associated with) "a port." A port is named by an integer. For instance, web servers typically listen using a socket bound to port 80.

There can be only one socket bound to a particular port at a time (on a single system). An attempt to bind a second socket to a port number results in an error. This means that we have to be careful to use different port numbers when running on klaatu.

It is a somewhat difficult (and, I hope, interesting) problem how we might agree on who uses what port number in a way that achieves our goals without too much work. I have implemented a heuristic that should be highly likely to avoid conflicts (and resembles things sometimes done in distributed systems). Basically, you should use your student ID to generate two valid port numbers. (Valid port numbers have to be chosen in a restricted range of integers.)

For this to work, you MUST edit the value assigned to variable MYID in HTTPServer.java:

    static final int MYID = 1234567;  // STEP 1 -- replace with your student ID

    static final int PORT_A = MYID % (65545-1026) + 1025;
    static final int PORT_B = PORT_A + 1;
  

Port conflicts could occur, but you'd have to be very unlucky to experience one.

What to Do First

  1. Create a directory, hw8 in your home directory on klaatu.
  2. Copy the files in klaatu:/courses/cse410/22wi/hw8/ to that directory.
  3. Edit MYID in HTTPServer.java
  4. Compile: $ javac *.java
  5. Run the server: $ java HTTPServer. It will print the port numbers it is using for DocA and DocB.
  6. Fetch DocA using your browser (which can be running on any machine, anywhere): http://klaatu.cs.washington.edu:XXXX where XXXX is the port number your server uses for DocA.
  7. Fetch DocB
  8. Answer the termination question, y or n, to terminate or continue

What to Do Next

Edit the code to use Java threads so that the server can handle requests in any order.

  1. Make HTTPSocket a subclass of Thread.
  2. HTTPSocket must implement a run() method, which is where it starts execution (once it starts execution).
  3. Creation of an HTTPSocket object is separate from starting it running as an independent thread. To do that, invoke the start() method on the HTTPSocket.
  4. Each HTTPSocket thread should sit in a loop handling requests. The main thread should go into a loop asking the user if they want to terminate execution.
  5. When the users asks for termination, the HTTPSocket threads are probably stuck on an accept() call waiting for user input. To unblock them, close the socket they're waiting on.
  6. To coordinate termination, make sure the main thread does a join() on the socket threads before returning.

Java Threads

There is endless information on the web about Java threads, including endless examples.

A particularly simple example is provided in /courses/cse410/22wi/lect16files on klaatu. It defines a class, Worker, that extends the Java Thread class, and a driver class, Example, that creates two Worker threads, sets them running, and waits for them to complete. Those are the operations you need in this homework.

As always, we welcome questions on the discussion board or to cse410-staff@cs.washington.edu.

What to Hand In

Hand in your source code files on gradescope.