CNT5505 Course Project 1
The code can
be written in both C/C++.
In a
peer-to-peer content distribution network, a client is a user who wishes to
download some files. Over the time he may have got a number of files, thus,
when asked, he can also upload some of the file he has to other clients. The
question is how to make other clients know that he has these files. There are
many ways to do this, and in our project we will adopt the simplest method, in
which there is a centralized server who keeps track of all the information of
the clients in the network (this is the ``tracker’’ in BT). In this project,
there will be n files where n is 64. Each client maintains a 64-bit vector, called ``file
vector’’ indexed from 0 to 63, in which bit i is 1 if it has file i and 0 otherwise. The purpose of this
project is to set up basic client-server communications.
For the
client:
1. Initialization.
The client will be invoked with a command line which contains two arguments.
The first argument may be the server’s IP address in dotted
decimal notation or the server’s domain name. If
it is the IP address, the client calls the gethostbyaddr()
function to get the domain name and prints out. If it is the domain name, the
client calls gethostbyname() to find the server’s IP address and prints it out. The second argument is the name
of a config file which the client reads to
find its id, the server’s listening port, its own listening port, and its
initial file vector; the client should print out such information. The config files are different for different clients and will
be supplied by me.
2. Connect to the server. The client tries to connect to the server by first creating a socket
and then calling the connect() function. If the
connection is successful, the client prints out a success message; otherwise it
quits. In this assignment, all connection is TCP.
3. Report to the server. The client then sends the server a message with information of its id,
its listening port, and the file vector. The client does this by filling in a
``Packet’’ struct defined in common.h,
and send the struct to the server.
4. Wait for commands. The client enters an infinite loop. The client will use the select() function to get user inputs and to read message
from server. It accepts two commands, ``f’’ and ``q’’:
· If the user types ``f’’, the client
will ask which file the user wants and the user will input the file index. If
the user inputs, say, 10, the client first checks if it has file 10. If yes, it
prints out a message like ``I already have file 10.’’ Otherwise, it sends a
message to the server saying that ``can you tell me who has file 10?’’. The
server will reply with a list of clients who has file 10. After receiving the
server’s message, the client prints out the list, then waits for the next
command.
· If the user types ``q’’, the client
quits: a) it first sends the server a message saying that it wishes to quit, b)
waits until server closes the connection, c) terminate the program.
5. Auxiliary functions. The client also reads commands from the server. For this project there
is only one command: quit. If the server sends the client this command, the
client will close the connection by calling the close()
function and exit.
For the
server:
1. Initialization. The server first creates a socket, binds it to port 5000 (5000 is the
so-called ``well-known’’ server listening port for our project), and calls the listen() function to wait for connection requests from this
socket.
2. Accept requests. If there is a connection request, the server calls accept()
to accept the request. The integer returned by accept()
is the socket id through which server will communicate with this client. The
server then reads the message the client sends which contains the client’s ID,
listening port, and file vector.
3.
Answer client queries. If a client sends the server a query for a file, server first
prints out the client’s ID, IP address (the client’s IP address can be found
when calling the accept() function and can be later
stored), and the file index the client is asking for. The server then prints
out the IDs of all clients who have the file (who have reported to the server
by this time), and sends this list to the requesting client.
4. Respond to user command. The server receives
only one command from the user, ``q.’’ If the user types in this command, the
server sends to all clients a ``quit’’ message, and waits until all clients
have closed their connections with the server, after which it will exit.
5. Respond to client quit message. If a client sends a
``quit’’ message to the server, the server prints out a message like ``(client ID) at (IP address) wishes to quit,’’ then closes the connection with this client.
You can
write your own code from scratch or can start with a template code (here) which also
includes the client config files. To use it, copy
template.tar to your working directory, type ``tar xvf
template.tar,’’ then type ``make.’’ Then you will see two executables, server,
and client. To invoke the server, simply type ``./server.’’
There are many ways to invoke the client, which you may find out by reading the
client code. One simple way is, for example, by typing ``./client
–m localhost
-h 5000.’’ It is recommended that when debugging, run 3-4 client
processes and the server process on the same machine.