CS 4251 Computer Networks II: Project
Due by 5pm April 10, 2001
email to cs4251@cc.gatech.edu
Assignment
Client/Server architecture may be the most popular architecture for
network applications today. In such architectures, however,
the limitation of server resource is often the bottleneck of scalalibity.
In this project you will study the limitation of a single server and try
some ideas for solving this problem with a backup server. This project
includes two phases. In Phase I, you are going to create a concurrent file
server and a client running on top of TCP. The server should
be designed to handle as many concurrent connections as possible.
You also need to create a monitor program collecting throughput information
from all the clients via UDP. Your grade will partially depend on
the number of clients your server can handle and the aggregate bandwidth
at the client ends. After finishing Phase I, you should be able to
find the factors that limiting the number of clients your server
can handle. In Phase II, you are going to build a backup server
that can take over the "overflowing" connections from clients when the
original server is overloaded. To do this, you need to revise the
file server and client you implemented in Phase I so that the client can
be informed the location of backup server when its connecting request needs
to be redirected.
Environment
All projects are to be worked on individually. The client, server and monitor
programs should be written entirely in C/C++ and working on the systems
in the Solaris lab ( Baird cluster ) of CoC.
The TAs provided two source files: datasource.c,
datasource.h , which you will need in your programs.
The usage is described later in this assignment.
Phase I
In this phase, you need to implement three programs: client, server and
monitor. The relationship among the three entities is shown in the
following figure. The client requests files from the server and the server
transmits files to the client via TCP. The client measures the transmission
throughput every 1 second and reports the throughput to the monitor.
The monitor records every report into a file and periodically(every 5 seconds)
displays on screen the overall throughput of all clients in the past 5
seconds.
Server
Your server program should have the following name and arguments:
server port#
Where port# is the port number your server is listening on.
You are free to choose how to handle multiple concurrent connections.
Some choices are using fork(), select(), poll() and pthread, among others.
After the server acceptsa connection, it should call sopen_rd() , which
is provided by the TAs in "datasource.c", to
open a virtual file for read. sopen_rd() returns a handle that can
be passed to sread() to read data from it. The data then should be
transfered to the client. The main reasons to use a virtual file include:
-
It uses no real file descriptors, which is one of the constraints of how
many connections a server can accept
-
It does not rely on actual file system calls. Reading for an NFS file will
inevitably interfere with your TCP connections
-
It has infinite length, which is good for performance measurement
If the server cannot handle a client because of resource limitation, the
server should gracefully reject the connection request, i.e. a server should
never crash because it is getting more requests than it can handle.
Client
Your client program should have the following name and arguments:
client clientID servername serverport# monitorname monitorport#
Where servername and serverport# are the host name and port number on which
your server is listening, monitorname and monitorport# are the hostname
and port number on which your monitor is listening, and clientID is a unique
integer to identity this client to the monitor.
After establishing a connection, the client should call sopen_wt(),
which is provided by the TAs in "datasource.c",
to open a virtual file for write. sopen_wt() returns a handle that
can be passed to swrite() to write data to it. swrite() will verify
the integraty of the received data . Each client also measures the throughput
every 1 second and report it to the monitor.
If the connection is rejected, the client exits.
Monitor
Your client program should have the following name and arguments:
monitor port# logfile
Where port# is the port number your monitor is listening on and logfile
is the file name where you record the report from the clients.
Each line of the logfile records one report in the following format:
clientID time throughput
Where clientID , time, and throughput records the originator, receving
time and the 1-second throughput of the reporting client. Note here that
the time is relative to the starting time of your monitor with
second
as the time unit. The throughput should be measured in bytes.
The monitor also displays on "standard output" the overall throughput
of all clients every 5 seconds. The format is shown below:
time numofclients overallthoughput averagethroughput
Where time is the current time in the same format as the time reported
by clients. "overallthoughput" and "averagethroughput" are computed using
the aggregated throughput in the past 5 seconds.
Testing and Performance measurement
You should test your program on the machines in the Solaris Lab (Baird
cluster ) in the CoC building. Start your server program on a machine
and your monitor program on another one. Then you start your clients
on a third machine (all clients are going to run on this machine).
Incrementally start more clients until the server starts to reject them.
You need to process your logfile to determine the maximium number of
clients your server can support and generate four graphs:
-
The average throughput vs. number of clients
-
client end thoughput distribution when there are 16 clients accessing
your server
-
client end thoughput distribution when there are MAX clients in connection,
where MAX is the maximum number of clients your server can support.
You can use a script language such as PERL or write your own C/C++ programs
to do performance analysis. Do not turn in these programs, but describe
how you did it in the report.
Phase II
In this phase, you need to revise the client and server programs you implented
in phase one to enable request redirection and server replication. In this
phase, we pretend a server can only handle 8 connections. Initially,
only one server is running and it will handle the first 8 connections.
When the 9th connection comes, the server should spawn a copy of itself
as the first backup server on the same machine but on different port
(You can use UNIX system function system to do it.) Subsequent
requests to the server are redirected to the first backup server.
When a request is redirected, the server should notify the client of the
port number of the first backup server so the client can connect
to it. Simularily, the first backup server will handle up to 8 connections.
It will spawn the second backup server and redirect requests to it when
necessary. You are required to handle up to 24 clients in the system. So
some requests will be redirected twice. The following figure
shows relationship between server, client, monitor and backup server.
Your backup servers shoud be clones of the original server and spawned
only when needed. Your server program should have the following name
and arguments:
server2 port#
The client programs should have following name and arguments:
client2 clientID servername serverport# monitorname monitorport#
The input and output of monitor programs is the same as it is in
Phase I.
You also need to measure the performance of phase two and generate
a client end throughput distribution when you have 24 clients in connection
(8 on the server and 8 on the first backup server and 8 on the second
backup server ).
Turning in Your Program
You should submit a .tar.gz compressed archive, one for each phase.
The archieves should include:
-
the source code for your programs
-
a makefile
-
a report discussing how your program works, including any known problems
and constraints, the maximum number of connections your server can
handle in phase I and the factor determines this number, how do you
measure the performance, the performance data and curve of your client-server
systems.
Be careful not to overwrite any of your own files when creating the archive.
An example shell session may be:
% tar cvf archive.tar *.h *.c *.cpp Makefile README report
% gzip archive.tar
where % is the shell command prompt and the above two commands
should create a file archive.tar.gz for you to turn in. Remember
to include all necessary source code, Makefile, and documentation
in the archive. Please do not include any .o file, executable,
or core-dump in the archive. If you are not familiar with
tar,
please read its on-line manual.
Finally, email the archive as an attachment to cs4251@cc.gatech.edu.
Grading Criteria
Phase I (40%)
Successfully compiles and runs
(actually a prerequisite for everything else) |
15% |
| Correctly implements the client program |
10% |
| Server successfully handles 16 concurrent connections from clients |
10% |
| Server can handle more than 50 concurrent connections from clients |
5% |
Phase II (30%)
Successfully compiles and runs
(actually a prerequisite for everything else) |
5% |
| Correctly implements the client program |
10% |
| Server spawn and redirect correctly for clients 9 - 16 |
10% |
| Server spawn and redirect correctly for clients 17- 24 |
5% |
Monitor, Report and documentation (30%)
Monitor program working correctly
(a prerequisite for a correct report) |
15% |
| Report |
10% |
| Documentaiotn,coding style |
5% |
Hints and Constraints
-
Make sure your archive is complete, your program compiles smoothly on Solaris
2 systems with /usr/local/bin/gcc, and your program displays
a suitable error message for any exception condition and never seg-fault,
core-dump, or hang.
-
Do not modify the source files that provided by the TAs.
-
Use the default limits of Solaris, i.e. do not use unlimit
command and system calls, etc. to change them.
-
Your program should be modular and well commented.
-
The program must be your own work. You can reuse any of Comer's
code and Code
from "the Pocket Guide to TCP/IP Sockets" in your projects. But any
other existing code must be cleared with us first.
-
Make sure to kill all the server and client processes when you finish.
-
Start early. You have about five weeks to work on this project. Use at
command to schedule large scale testing at night when you can.
Have fun!