CIS 432/532 Introduction to Computer Networks
Fall 2001

Program #1: Chat Application
Due 20th November online by 5pm

Overview

In this assignment, you will write a client-server chat application. The server will allow any number of clients to connect to it and participate in real-time, text-based chat sessions with other users. In addition to typing messages to other users, clients will be able to join groups and send simple queries to the server. The server will keep track of the state of each client and relay messages between clients appropriately.

Client User Interface

When the client is started, it automatically connects to the chat server. From this point on, the user can type either commands or messages. Each line the user types ends when a carriage return is entered; the client then interprets the line as either a command or message and takes the appropriate action.

Commands start with a '/' character and end with a carriage return, with each word separated by one or more spaces. All commands are sent to the server, which interprets them and returns a response. Some commands are available only when a user has joined a group. Anything the user types that does not begin with a '/' is considered to be a message. The following chart lists the available commands, with parameters given in italics. For each command, the chart indicates when the command is available, its meaning, the response that is printed, and the clients for whom this response is printed. Only successful responses are sent to other group members.

Type Command Available Meaning Client Response Printed For
Group Management /create [group] Out of a group The user creates a group with the given name. [group] created
or
[group] already exists
or
You are in [group]
User who created the group.
  /delete [group] Out of a group The user deletes the group with the given name, but only if it is empty. [group] deleted
or
[group] does not exist
or
[group] is not empty
or
You are in [group]
User who deleted the group.
  /join [group] Out of a group The user joins a group with the given name. [nick] joins [group]
or
[group] does not exist
or
You are in [group]
All users in the group.
  /leave [group] In a group The user leaves the group with the given name. [nick] leaves [group]
or
You are not in [group]
All users in the group.
  /list Always List all the available groups. [Group1]: [Nick1], [Nick2], [Nick3]
[Group2]
: [Nick4], [Nick5], [Nick6]
....
User who asked for the list.
           
General /nick [nick] Always Changes the user's nickname (default is the login name) [nick] changes his name to [nick]
or
There is already a user with [nick]
All users in the group or just the user if out of a group.
  /who Always Lists the users on the system, either for all groups or for just the group the user is in. [Nick1]: [LoginName], [IP], [Port], [IdleTime]
[Nick2]: [LoginName], [IP], [Port], [IdleTime]
....
User who asked for the list.
  /whois [nick] Always Lists just the given user. [nick]: [LoginName], [IdleTime]
or
There is no user with [nick]
User who asked for the information.
  /quit Always Exits the program [nick] quits All users in the group or just the user if out of a group.
           
Messages /private [nick] [message] Always Sends a message only to the listed user. {[nick]: [message]}
or
There is no user with [nick]
User who receives the message.
  [message] In a group Sends a message to all users in the group. [[nick]]: [message]
or
You are not in a group
All users in the group except the one who sent it.

When a client is started, it automatically connects to the chat server and presents the user with a prompt:

>

Whenever the user has joined a group, the prompt changes to indicate which group the user is a member of. For example, if the user has joined the 432 group, the prompt will be:

432>

The following text gives a sample session with the chat application:

>/nick hamburgler
Joe changes his name to hamburgler
>/join mcdonalds
hamburgler joins mcdonalds
mcdonalds>hello everyone
mcdonalds>/who
ronald: jsmith, 128.223.4.55, 5007, 1 minute
fryguy: peter, 128.223.4.78, 5010, 2 minutes
frygal: helen, 128.223.4.79, 5010, 0 minutes
hamburgler: joebob, 128.223.4.75, 6040, 0 minutes
mcdonalds>
[frygal]: welcome back!
mcdonalds>/private frygal you're always here!
mcdonalds>
{frygal: hey, I like it here, what can I say?}
mcdonalds>/leave mcdonalds
hamburgler leaves mcdonalds
>/quit
hamburgler quits

Chat Protocol

It is important for the chat protocol to be standardized so that different client and server implementations can talk to each other. This section describes each message sent between the client and server using the chat protocol. Each message is sequence of lines, with each line terminated by a newline character ('\n'). The entire message is terminated by a null character ('\0'). Each parameter in the message must be a single word, with a single space separating each word.

  1. user [LoginName]

    This is the first command a client must send after connecting to the server. If the client issues any other commands before this command has been sent, the server will always return the message:

    error login needed

    The command identifies the user to the server with his/her Unix login name. The server identifies the client by its IP address and port number, then uses the login name as the default nickname for the user. The login name is also printed for the who and whois commands. After storing the user's login name, the server returns the message:

    success

    These actions are taken and this result is returned only the first time the message is sent to the server. All subsequent times this command is sent the server responds with the message:

    error login already

  2. create [group]

    The client sends this message to the server to create a group. The server keeps a list of all the groups that have been created and ensures that each group identifier is unique. If the user is in a group, the server returns the message:

    error in [group]

    If the given group already exists, the server returns the message:

    error group exists

    Otherwise, the server creates the group and returns the message:

    success

  3. delete [group]

    The client sends this message to the server to delete a group. If the user is in a group, the server returns the message:

    error in [group]

    If the given group does not exist, the server returns the message:

    error group doesn't exist

    If the given group exists but is not empty, the server returns the message:

    error group not empty

    Otherwise, the server deletes the group and returns the message:

    success

  4. join [group]

    The client sends this message to the server to join a group. If the user is in a group, the server returns the message:

    error in [group]

    If the given group does not exist, the server returns the message:

    error group doesn't exist

    If the given group exists, the server adds the user to the group and returns the message:

    success

    The server also sends the following message to all other clients in the group (not including the one that just joined):

    notice join [nick]

    indicating the user that has joined the group.

  5. leave [group]

    The client sends this message to the server to leave a group. If the user is not in the group or if the group does not exist, the server returns the message:

    error not in group

    Otherwise, the server removes the user from the group and returns the message:

    success

    The server also sends the following message to all clients in the group (not including the one that just left):

    notice leave [nick]

    indicating the user that has left the group.

  6. list

    The client sends this message to the server to get a list of all the groups. The server returns the message:

    groups
    [Group1]: [Nick1], [Nick2], [Nick3]
    [Group2]
    : [Nick4], [Nick5], [Nick6]
    ....

    The list ends with a blank line. Users who are not in a group are not listed.

  7. nick [nick]

    The client sends this message to the server to change the user's nickname. Initially, the nickname is set to the user's login name. If a user already exists with this nickname, the server returns the message:

    error already [nick]

    After storing the user's new nick, the server returns the message:

    success

    If the user is a member of a group, the server also sends the following message to all other clients in the group (not including the one that changed its nickname):

    notice nick [oldnick] [newnick]

    indicating the nickname change.

  8. who

    The client sends this message to the server to get a list of users. If the client is not a member of any group, the server returns a list of all the users on the system. If the user is in a particular group, the server returns a list of only the users in the same group. The server returns the message:

    users
    [Nick1]: [LoginName], [IP], [Port], [IdleTime]
    [Nick2]: [LoginName], [IP], [Port], [IdleTime]
    ....

    where the idle time is the number of minutes since the user last sent a message. The list ends with a blank line.

  9. whois [nick]

    The client sends this message to the server to get a list of information on a particular user. If no such nickname exists, the server returns the message:

    error none [nick]

    Otherwise, the server returns the message:

    user
    [Nick]: [LoginName], [IP], [Port], [IdleTime]

  10. quit

    The client sends this message to the server to quit the application. The server removes any data it keeps on this user and returns the message:

    success

    If the client is a member of a group when it quits, the server sends the following message to all other clients in the group:

    notice quit [nick]

  11. private [nick] [message]

    The client sends this message to the server to send a private note to a particular user. If no such nickname exists, the server returns the message:

    error none [nick]

    Otherwise the server returns the message:

    success

    Then, the server sends the message:

    private [nick] [message]

    to the specified user. The nick is set to the nickname of the person sending the message.

  12. message [message]

    The client sends this message to the server to send a message to the other members of its group. If the user is not in a group, the server returns the message:

    error not in group

    Otherwise, the server returns the message:

    success

    Then, the server sends the message:

    message [nick] [message]

    to all other users in the group, not including the one that sent the message. The nick is set to the nickname of the person sending the message.

Any time the server is unable to parse a message from the client, it responds with the message:

error parsing

When the client receives this message, it prints:

Chat protocol: server parsing error: command

where command is the command sent to the server. Likewise, If the client is unable to parse a response from the server, it prints:

Chat protocol: client parsing error: response

Server Implementation

The server must do a number of tasks:

You should not worry about making the server multi-threaded. A single thread of control is fine. However, you will need to do some relatively complex socket programming to handle input and output with all of the sockets from the clients. In particular, you will need to allow simultaneous connections from any number of clients. Be sure to read about the select() system call in the socket programming book and in the online manual.

Command Lines

The server should take the following arguments:

  Argument Definition
  -p [port] Port number of the server.
  -d Print debugging information.

The client should take the following arguments:

  Argument Definition
  -s [server] Machine name of the server (i.e. ix.cs.uoregon.edu).
  -p [port] Port number of the server.
  -d Print debugging information.

All arguments can be given in any order. By passing these arguments on the command line, you can try running your server on different machines and ports. You can use the debugging flag to print out any helpful debugging information you want, but you should never print debugging lines if the flag is not specified on the command line. If the user does not supply the correct arguments, you should print an error message indicating how to use the program and exit.

Error Checking and Debugging

You should check for errors resulting from system calls. If a system error occurs, use the perror() interface to print out its corresponding code and then immediately exit the program. You must use the debugging interface defined in debug.h to print out any debugging comments. This way you can turn off the extra comments via the command line.

Compiling and Running

You must supply a Makefile that will compile your C code. Your server executable must be called chat-server and your client executable must be called chat.

Grading

Your program will be tested by running the chat program to be sure it works as specified. In particular, we will check to see whether your server and client have been written according to the protocol spec. This is the main criteria for grading! We will release a sample client and server so that you can check your programs for interoperability with our solution.

Any program that does not compile will receive a 0.

Turning in the Assignment

You must submit all your source code and documentation online. Do not submit any object code. Use the submission instructions for this program, which are available in the Schedule section of the class web page.

You must also print out and fill in the survey for this program. The survey is also available in the Schedule section of the class web page. Turn this in to my office on the due date (or put it under my door).