CSC 209H: Assignment 4
Weight: 10% of course grade.
Due date: 10:00 p.m. Thursday December 8
Introduction
In this assignment, you will be writing a simple client-server chat system.
You will be writing two C programs, one server and one client, that
implement a basic protocol allowing users to communicate.
Revised: the requirements to implement some commands
have been removed. See the comments below in red.
chatserver
Your server will be called chatserver. It will listen on the
specified port for client connections, maintain a list of currently
connected users, handle requests from users, and pass messages between
different users.
Once a client connects, your server will handle a sequence of commands
sent by the client. A list of commands a client may send is below.
Each command is terminated with a null '\0' character.
- HELLO name
This command can and must only be specified as
the first command after a client connects.
name is required, and identifies the user's name that is
to be associated with this client.
The server replies with one of three statements:
OK - name is accepted
NO Name already used - another client is currently connected
using the same name. The server should terminate the connection.
NO Name invalid - the name is invalid.
The server should terminate the connection.
- WHO
The server responds with a number n,
the number of currently connected and identified clients,
expressed as a null-terminated string.
Following is n null-terminated strings, reporting the name
of each such connected user, in any order.
- WRITE name msg
The server sends a line to the specified user in the format:
MSG from msg
where from is the name of the sending user.
The server replies with one of the statements:
OK - the message was sent (but not necessarily received)
NO User does not exist - the user name
is not currently connected
NO Name invalid - the name is invalid.
- YELL msg
Sends msg to all current users.
Its effect is same as WRITE, except to everyone and never fails
(the server replies OK).
-
REQUIREMENT removed (you do not have to do this anymore):
ROSHAMBO n
Enter Roshambo mode. The server forks a child process, which execs a
program specified at compile time (default is rps1).
If the fork or exec fails, the server replies "NO" and
specifies the error, otherwise initiates n rounds of Roshambo
between the client and the Roshambo program. Your server will follow the
rps protocol specified in Assignment 3 with the program. For each round
the server will send GO to the client, the client will respond
with a number 0, 1 or 2, and the server will reply with a number
obtained from the program, followed by the appropriate string
"You win",
"You lose" or
"You tie".
After n rounds, the server replies with a line like
SCORE 4 to 1 with 5 ties, you won
and returns to command mode. The client may send a command instead of a
throw by prepending a !. The special command EXIT
aborts the game and returns immediately to command mode. Upon returning
to command mode, the child processes is terminated.
The ROSHAMBO command is only valid in command mode.
The following rules and limits apply to the above commands
- name - a sequence of between 1 and 30 alphanumeric or punctuation
characters (no whitespace)
- msg - maximum 250 characters, terminated with '\0'
(spaces are permitted)
- n - an integer, expressed as a string
- All commands and replies are terminated with a null byte '\0'.
- Current user - a client which has successfully sent a HELLO
in the past
Your server must service all connected clients fairly. If a client makes
a request, it should not have to wait for another idle client to make a
request before it is serviced. (That is, use the select function.)
chatclient
The second C program you will write is a client program that will interface
with your server program via the protocol described above.
Your program should support being run in the following manner:
$ chatclient host [username]
host is the name or IP address of the server to connect to,
and is required.
username is the name to be used for the connection. If
username is not specified, the value of the environment variable
USER should be used.
Your client program will connect to the server, introducing itself with
the HELLO command, and reporting whether the connection is
successful or denied. It will then present a list of users currently
logged into the server, and process commands from the user.
The user may enter various requests, which the client will send as
commands to the server. The format of these requests are somewhat
inspired by IRC.
- message - anything the user types that doesn't start with a
'/'
will be sent as a YELL command (unless in talk mode, see below)
- /who - prints a list of users currently connected, obtained
via a WHO command
- /msg name message - will be sent as a
WRITE command to the given user
- /talk name - enter talk mode, exclusively sending
messages to name.
Every message will now only be sent to name via a
WRITE command until the user says /done
or the user decides to /talk to someone else or the server
informs the client that name is no longer connected.
- /done - ends talk mode (if a previous /talk
request is still active), or does nothing if already in normal mode
- /help - will print a list of requests that the user may type
- /quit (or signalling end-of-file) - terminates the client
-
REQUIREMENT removed (you do not have to do this anymore):
/play [n] - play a game of Roshambo via the ROSHAMBO
command. Your client will play n rounds (or one round if
n is not specified), and interpret the
next lines of input as a throw until a valid throw is given.
The client will send the throw, and report the result.
The user may abort the game by entering /done instead of a
throw, where the client should send the !EXIT command.
Each request will be a line of input read from stdin. If the
message is long (for example, more than 60 characters), the
client must break it up into multiple commands to be sent to the server.
A blank line on input should be ignored (and not sent as a message).
Whenever the client receives a MSG from the server, it will
print the message to stdout in the format:
<fromuser> message
where fromuser is the name of the user who sent the message.
Example
The following might be a sample execution of the program.
$ ./chatclient localhost me
Connected to 127.0.0.1 as me
janedoe
me
<janedoe> Anyone out there?
I'm here
<me> I'm here
/talk janedoe
how's the assignment going?
/done
<janedoe> We have an assignment to do?
<janedoe> I've got to go!
/msg janedoe Don't worry, it's pretty easy
janedoe is not logged in
/who
me
/quit
Hints, Tips and Clarifications
What to hand in
You will commit to the a4
directory of your CSC209
repository the following files:
- Your C source files for
chatserver
and
chatclient
- Any additional files needed by your programs (header files, etc.)
Makefile
, containing commands to compile
your chatserver and chatclient
simply by running
make
You are strongly encouraged to take advantage of the version
control system and commit your work frequently so that you can keep
track of your progress. Please note that perfectly fine (and even
recommended) that you keep any additional files related to this
assignment (such as files and scripts used for testing) under version
control. The markers will simply ignore such files.