CMPU 375 - Project 1 Due: by the end of the day (11:59 PM) on Wednesday, September 21st

Project 1 - Instant Messaging Client

Document revision: $Revision: 1.10 $

In this project, you will implement a client engine for a client/server instant messaging protocol.

Encoding of messages

Each message is encoded as a line of text in the UTF-8 character set encoding.  Each line ends with the sequence "\r\n" (CR followed by LF).

In Java, you can use the BufferedReader class to read lines as follows:

import java.io.*;
import java.nio.Charset;

Socket socket = ...

BufferedReader reader = new BufferedReader(
   new InputStreamReader(socket.getInputStream(), Charset.forName("UTF-8")));

String message = reader.readLine(); // Reads a single line of input

To write a line containing a protocol message, you can use the BufferedWriter class:

import java.io.*;
import java.nio.Charset;

Socket socket = ...

BufferedWriter writer = new BufferedWriter(
  new OutputStreamWriter(socket.getOutputStream(), Charset.forName("UTF-8")));

String message = ...
writer.write(message);
writer.write("\r\n");

Note that because messages are delimited by the end of line sequence "\r\n", you must be careful that this sequence does not appear in the message.  Therefore, any embedded '\n' characters (newline) must be encoded as a '\\' (backslash) character, followed by the character 'n'.  Any backslash characters in the message must be encoded as a sequence of two backslash characters ('\\', followed by another '\\').

Message formats

There are two message formats:

Format Contents
Format 1 <Message type> (SPACE <body>)optional EOL
Format 2 <Message type> SPACE <token> (SPACE <body>)optional EOL

EOL is the line termination sequence "\r\n" (CR, followed by LF).  SPACE is the space character ' ', Unicode character 32.

<Message type> is one of the following words:

HELLO
LOGIN
OK
REFUSED
AVAIL
NO_MESSAGE
CANNOT_SEND
GET_MESSAGE
SEND_MESSAGE
BYE
These message types are specified by the enum type edu.vassar.cs.cs375.im.MessageType.

<token> is a nonempty sequence of characters other than SPACE.

<body> is a possibly-empty sequence of characters that continues until the EOL sequence is reached.

Whenever the optional SPACE <body> sequence is not present, the body should be considered to be empty.

Client messages and states

The following messages are defined in the protocol:

Message type Purpose Message format Meaning of fields
HELLO Prompt client to log in 1 body ignored
LOGIN Log in to server 2 token is the user name of the user to log in; body ignored
OK Acknowledge successful LOGIN or SEND_MESSAGE 1 body ignored
REFUSED Deny login 1 if present, body describes why the login was refused
AVAIL Deliver a received instant message to the client 2 token is the user name of the sender; body is the text of the received instant message
NO_MESSAGE No instant message is available 1 body ignored
CANNOT_SEND Instant message could not be delivered to recipient 1 if present, body describes why the instant message could not be sent
GET_MESSAGE Poll the server to see if an instant message has been received 1 body ignored
SEND_MESSAGE Send an instant message to a user 2 token is username of recipient; body is text of instant message
BYE Log off of server 1 body ignored

The client protocol states and state transitions are shown in this diagram:

The edges leading out of each state specify what kind of message can be either received or sent.  Note that there are no states where it is legal to both send and receive a message.

Implementation

All of the software you need to compile and run the project is installed on the Sun workstations in the Asprey lab.

The source code you should use as the starting point is in project1_fixed.zip.  You can import this file directly into Eclipse: from the menu, choose

File->Import...->Existing Projects Into Workspace
then click "Select archive file", choose the file project1_fixed.zip, and click "Finish".

You can also compile the code from the command line using the ant command.

Your task is to implement the class

edu.vassar.cs.cs375.im.impl.ClientImpl
This class must implement the interface edu.vassar.cs.cs375.im.Client, which defines the client engine operations that will be used by the user interface code.  The javadoc comments in this interface will detail the requirements for implementing each method.

Using the design we discussed in class, the client engine will be run in its own thread.  The client engine will make calls to an object implementing an interface called "UserInterface"; for example, to display an instant message that has just been received.

For the sake of simplicitly, the client must poll the server periodically to see if an instant message is available to be received.  Here is what each iteration of the client polling loop should do:

if (user has typed an instant message to be sent) {
    send it
    continue loop
}

check server to see if an instant message has been received
if (a message was received) {
    display it
    continue loop
}

wait 250 milliseconds, or until the user types an instant message to be sent
continue loop

Testing your project

I have implemented a server, which will run on fac59.cs.vassar.edu, listening on port 8000.  You may want to try using telnet to connect to this server to experiment with the protocol:

% telnet fac59.cs.vassar.edu 8000

The server will simply close the connection if you send a message that is not legal in the protocol.

Once you have implemented the ClientImpl class, you can try running the GUI front-end to drive your client.  You can run this front-end, first add the "bin" directory in your compiled project to the CLASSPATH, and run the command:

% java edu.vassar.cs.cs375.im.ui.SwingUserInterface username fac59.cs.vassar.edu 8000

For username you can substitute any word with no embedded spaces: e.g., "Alice", "Bob".  You can use a single client to send instant messages to itself, or you can start two instances of the client with different user names, and send messages between them.

For even more fun, try starting two clients on different machines, and have them send messages to each other.

Submitting your project

To submit your project, create a zip archive of the project, put the archive in a directory called "project1", and then use the submit375 program to submit the directory.  Note that you need to be logged into one of the Sun workstations in the Asprey lab for this to work.

You may submit your project multiple times: the last submission before the deadline will be graded.

1. Creating the zip archive

To submit your project, create an zip archive of the entire "vassarim" directory containing your client implemention.

From the command line: First, open a terminal window and go to whatever directory contains the "vassarim" directory.  Then run this command:

zip -9r ~/vassarim_solution.zip vassarim

From Eclipse: In the Package Explorer, click on the "vassarim" project so it is highlighted.  From the menu, choose "File->Export...->Archive file".  Enter the filename

/home/username/vassarim_solution.zip
replacing username with whatever your CS username is.

2. Checking the archive

Make sure your submission contains the ClientImpl class!  To check this, run the following commands from a terminal window:

cd
unzip -l vassarim_solution.zip | grep ClientImpl
You should see something like the following output:
     6305  09-20-05 14:37   vassarim/bin/edu/vassar/cs/cs375/im/impl/ClientImpl.class
     5210  09-20-05 14:37   vassarim/src/edu/vassar/cs/cs375/im/impl/ClientImpl.java
Make sure that the file "ClientImpl.java" is present.

3. Putting the archive in a directory and submitting it

In a terminal window, run the following commands:

cd
mkdir project1
mv vassarim_solution.zip project1
submit375 project1