Assignment 2: Writing a Process-per-Request Web Client and Server
The purpose of this assignment is to deepen your understanding of the
ACE C++ toolkit to
perform network IPC between two host machines. We will expand assignment 1 by again write two programs: (1)
a web client and (2) a more robust web server that uses multiple
processes rather than multiple threads to process requests. In
brackets are some hints about what kinds of ACE classes you might want
to look up to do these, which are described in the ACE books and ACE online
documentation. The components that you must use for this
assignment are the ACE C++ socket
wrapper facades and ACE_Process_Manager. The other
hints are simply for your convenience.
Web Client
As before, the web client program should do the following activities:
- Read the URL and the server port number from the command
line. Create a socket that is connected to the server machine at the
specified port (e.g., HTTP port 8080) [ACE_INET_Addr,
ACE_SOCK_Connector, ACE_SOCK_Stream].
- Send a request to the web server using the HTTP protocol format.
This will look something like this:
GET /index.html HTTP/1.0\n\n
Note that it's very important to include the two trailing newlines --
they are required by the HTTP protocol.
- Read all the data from the HTTP connection and write it to a
temporary file created in your web cache (e.g.,
/tmp/yourloginname) on the local host [creat,read/write].
- The following portion of the web client is just for the
graduate students in the class. Spawn an external viewer to
display the file. You can determine the type of viewer to spawn in
two ways:
- Client-side file suffix -- The client can use the
file suffix (e.g., *.ps should spawn ghostview, *.gif should spawn xv,
an html file should spawn lynx, and a regular text file should spawn
/usr/ucb/more, etc.). If the file is compressed (e.g., *.gz, *.Z, or
*.zip) then uncompress it before viewing it.
- Server-side MIME content type information -- A more
robust way to determine what type of the viewer to spawn is to
utilize the Content-type: header returned by the server.
For instance, the GET /index.html HTTP/1.0\n\n request
from the client will return the following header:
HTTP/1.0 200 Document follows
Date: Wed, 11 Sep 1996 23:28:40 GMT
Server: NCSA/1.5.2
Content-type: text/html
Your client can simply parse this information and use it to determine
which viewer to spawn. BTW, this solution is the one used by web
browsers.
The client should simply print out the appropriate error message
[perror] and exit with a return status of 1 if any of the system calls
fail to work properly. If everything works correctly, the program
should exit with a return status of 0.
Web Server
The concurrent multi-process server program should do the following
activities:
- Create an Internet domain ``passive-mode'' stream socket on a
port number specified on the command line
[ACE_SOCK_Acceptor] and wait in the master process for connections to
arrive from clients.
- When a client request arrives, accept the connection
[ACE_SOCK_Acceptor::accept, ACE_SOCK_Stream] and spawn a worker
process [ACE_Process_Manager::spawn]. The master process should go
back to listening for incoming client requests in the event loop while
the new process performs the client request. Your worker process
should perform the data transfer itself, e.g., rather than using
cat.
- The newly spawned worker process should read in one HTTP request
such as
GET /index.html HTTP/1.0
and try to open the file in your local web directory
[ACE_FILE_Connector].
- Assuming open succeeds, the worker process should transfer the
file back to the client.
- The server should not exit unless you explicitly kill it via a
signal (e.g., SIGINT). You should add a signal handler
[ACE_Sig_Action] that performs any termination code necessary to
gracefully shutdown the server upon receipt of a signal. For this
assignment, make sure that you use a portable and robust mechanism for
closing down the server.
Comments
Although this assignment is fairly easy to describe, there are some
subtleties involved in making it work correctly. In particular, you
will need to learn about many details such as network addressing,
remote host identification, signal handling, process creation and
termination, etc.
In addition, please note that although we will use the ACE C++ socket
wrapper facades, you can actually communicate between processes on the
same host for testing purposes. However, the same programs will work
for communicating between processes on two separate host machines,
i.e., only the addresses will be different!
References