This assignment gives you a chance to become familiar with
concurrent network clients, servers, covering topics including
threads, synchronization, wait/notify (monitor), asynchronous I/O,
Update: [2/14/2012] We have removed the POST method.
Due: Parts 1, 2, and 4 (for multithread part) check point: 11:59 PM, Feb. 15; All Extended: 11:55 PM Feb 22.
The server that we will design is a simplified version of HTTP 1.0. A server is started with a document directory <doc root>. The most basic application message, encoded in ASCII, from the client to the server is:
GET <URL> HTTP/1.0 CRLF
where CRLF is carriage return and line feed, representing an empty line. This request asks for the file stored at location <doc root><URL>.
For example, if <doc root>=/tmp/mydoc, and <file> is /file1.html, the server will return the file /tmp/mydoc/file1.html, if it exists.
The basic reply message from the server to the client, encoded in ASCII, is:
HTTP/1.0 <status code> <message>
Server: <your server name> Content-Type: text/html Content-Length: <length of file> CRLF <file content>
CRLF again represents an empty line. If the file is found and readable, the returned <status code> is 200 and you can give a message such as OK. Otherwise, please give an error code of 400. If you are curious about HTTP error codes, you can see http://www.ietf.org/rfc/rfc1945.txt. You can use Java File class to obtain file size.
Your test client should be multithreaded. The client can generate
test requests to the server with the following command line:
%java SHTTPTestClient -server <server> -port <server port> -parallel <# of threads> -files <file name> -T <time of test in seconds>
In particular, the <file name> is the name of a file that contains a list of files to request. For example, a file may look like the following:
file1.html file2.html file3.html file1.html
Then each thread of the client will request file1.html, then file2.html, then file3.html, and then file1.html. The thread then repeats the sequence. The client simply discards the received reply. The client stops after <time of test in seconds>. The client should print out the total transaction throughput (# files finished downloading by all threads, averaged over per second), data rate throughput (number bytes transmitted, averaged over per second), and the average of wait time (i.e., time from issuing request to getting first data). Think about how to collect statistics from multiple threads.
In class we have covered multiple approaches to implement a server:
per request thread;
thread pool with service threads competing on welcome socket;
thread pool with a shared queue and busy wait;
thread pool with a shared queue and suspension;
In this part, you will implement the first 5 approaches and
compare their performance using your test client or a browser. You
can feel free to reuse the example code provided in class.
Following Apache configuration style
server starts by reading a configuration file:
%java <servername> -config <config_file_name>
The basic configuration parameters are listening port and
Listen <port such as 6789>
DocumentRoot <root dir>
For a thread pool based server, the configuration file allows specification of the number of threads:
<number of threads>
The cache size can be specified in the configuration file:
CacheSize <cache size in KBytes>
To simplify your server, there is no cache replacement; i.e., when the cache is full, no addition to the cache.
You can always specify some
configuration parameters in the command line, e.g., java
<servername> -ThreadPoolSize <size>. A commandline
specification will overwrite the configuration file specification.
We recommend that you consider a hash map in your program to
Your server must support the following:
In this part, you implement an asynchronous server with function
as Part 2. We have the following requirements:
Please read the source code of x-Socket, a high performance software library for reusable, asynchronous I/O servers. Please discuss in your report the following questions (please refer to the line numbers of the source code when discussing the design):
To conduct the testing, you will need to setup the
DocumentRoot at the server. It is highly recommended that you
generate a number of files of different sizes under
DocumentRoot named such as file1.html, file2.html, ...,
file1000.html. If you download gen.tar,
and untar it (tar -xvf gen.tar), you will see a directory
named doc-root and a directory named request-patterns.
To compare the performance with Apache, we will use the department zoo Apache server. We will use /home/httpd/html/zoo/classes/cs433/assignments/prog1/www-root to store testing files. Suppose we want to fetch /home/httpd/html/zoo/classes/cs433/assignments/prog1/www-root/html-small/doc1.html.
To use the department Apache server, since the department server has set DocumentRoot as /home/httpd/html/zoo, the URL should be:
To use your server, suppose you set the DocumentRoot as /home/httpd/html/zoo/classes/cs433/assignments/prog1/www-root, and you run your server on cicada.cs.yale.edu at port 9876. Then the URL is:
During your async i/o design, think how you implement a finite state machine to handle each request (e.g., initial state after accepting a connection, what other states). Java async i/o does not allow you to select events on a file channel. There are can be multiple design options to handle file i/o:
Use standard file i/o by assuming that file system is fast and will not become bottleneck;
Try out mapped file i/o:
FileInputStream fin = new FileInputStream(args);
FileChannel in = fin.getChannel();
ByteBuffer input = in.map(FileChannel.MapMode.READ_ONLY, 0, in.size());
Try out direct transfer: See FileChannel.transferTo;
Use standard file i/o and use a thread pool to help with reading files.
Last Update: February 07, 2012 09:59:24 PM -0500