Project 2: Instant Messaging
6.005 Elements of Software Construction
Fall 2007
Due: Tuesday, October 16, 5:00 PM
Instant messaging (IM) is a staple of the web and has been around
almost since its inception, starting with simple text-based programs
like talk and
IRC and progressing to
today's GUI-based IM clients from Yahoo, Microsoft, AOL, etc.
In this project you will design and implement a
text-based IM system (both the client and the server).
The following characteristics constrain the design space of an IM
system:
- Real-time communication. An IM conversation happens in real
time: one person types some text, presses "enter," and the other
person (almost) immediately sees the text.
- Number of parties. An IM conversation can happen between
two or more people. Some systems only allow two people to communicate;
others allow more than two people. Most systems allow a person to be
involved in multiple conversations at the same time.
- Based on typed text. The main mode of communication is via
text, as opposed to voice or video.
- Connected over a network. The parties involved in the
communication may be in physically remote locations, and are connected
over the internet.
Your task will be to design a text-based IM system
with the above properties, as well as additional properties
that you will incorporate into your design.
The purpose of this project is twofold. First,you will learn
several Java technologies, including networking (to support
connectivity over a network), sockets and I/O (to support real-time,
text-based communication), and threads (to support two or more people
communicating concurrently). As in project 1, you will have the
opportunity to use state machines to specify certain aspects of the
system's behavior.
More importantly, you will start learning how to take a set of
high-level, informal requirements and iterate through the design,
specification, implementation and testing of an end-to-end system.
Implement an IM system in Java with the following properties.
-
Client. The client is a program that opens a
network connection with the IM server at a specified IP address
and port number. Once the connection is open, the client program takes
input from the user (as text, from the console), and forwards the
input to the IM server. The client program also receives text from the
server and displays it to the user. If the server terminates the
connection, the client program notifies the user that the connection
has been terminated, and exits. You do not have to write the
client program. A client program that satisfies these requirements
already exists on almost all operating systems, called telnet.
You can run telnet by opening a command prompt
and typing telnet hostname port.
-
Server. The server is a program that accepts connections
from clients. A server should be able to maintain an unlimited number
of open client connections, and clients should be able to connect and
disconnect as they please.
The server is responsible for managing the state of both clients
and conversations.
-
Conversations. A conversation is an interactive
text-exchange session between some number of clients, and is the
ultimate purpose of the IM system. The exact nature of a conversation
is not specified (although the hints section details a
couple possibilities), except to say that it allows clients to send
text messages to each other.
- Client/server interaction. A client and server interact by
exchanging lines of text. A text-based protocol allows a client to send
any necessary directives to the server such as joining a conversation,
sending a message, etc. The protocol is not specified. It should,
however, allow for the following functionality:
- A client should be able to query who is online.
- A client should be able to create a conversation.
- A client should be able to join a conversation.
- A client should be able to leave a conversation.
- A client should be able to exit the system.
- Authentication. In a production system, logging in as a
client would require some form of
password authentication. For simplicity, this IM system will not use
authentication, meaning that anyone can log in as a client and
claim any username they choose.
- Prepare. Complete the lab.
- Define a conversation. Define a precise notion of
conversation in your IM system. See the hints on how to do this step.
- Define the commands. Define a set of commands for
the IM client that allow the client to perform the actions stipulated
by the specification.
- Specify the client/server protocol. Create a specification
of the
text-based client/server protocol as a state machine. The state
machine must include the possible transitions, the state of the
server, and of the client if it stores any state.
- Design. Come up with a simple and
clean class design that minimizes the risk of concurrency bugs
(like race conditions and deadlocks), and that also supports easy
unit testing of your state machine.
Write a brief argument explaining how the design achieves this.
The hints below may be helpful.
- Implement the protocol. You can use what you learned in lab as
a guide to using Java's networking facilities.
- Test. There are no staff-provided JUnit tests for this project,
because the design of the protocol is in your hands. However, you should create
a small number of unit tests for your server. Use your state machine
specification to devise a coherent testing strategy, so that the test cases you
choose achieve some reasonable coverage. See the hints on how to design your server so that it's easy for
your unit tests to drive.
- Iterate. You will probably need to iterate, making
adjustments to the design and the code until you have a working
program that satisfies the specification.
- Extend. Think of two features of an IM client that you
would like to implement in your IM client. You don't have to model
these features with state machines (but you can if you want). Possible
ideas: a client having the ability to change status among "online,"
"offline," "busy," etc. Or giving the client the ability to request
the transcript of a specific conversation. In short, anything that you
would like to implement that may or may not be part of existing IM
systems.
- Demonstrate. At your grading meeting, present your IM
client to your TA. The
presentation must include: (1) an overview and justification of the
design choices, (2) a walk-through of the protocol, and (3) a demo of
the IM client in action, showing how it implements the protocol.
The lab code includes several classes that
you became familiar with during the lab, and which you can use as a
starting point. Designing your chat server and deciding how
to divide it into modules is in your hands.
Your deliverables for the project are: the command specification; state
machine model; the code; any automated tests you may have written for
the code; and any commentary you wrote to explain the decisions you
made, especially your argument that your design is free of concurrency
bugs.
All commentary and diagrams should be in plain text or PDF and
saved at the top level of your project directory.
Each PDF or text file must contain an appropriate title describing
it, along with the Athena usernames of you and your partner.
Make sure your files have the appropriate extension (.pdf or .txt).
90% of your grade will be allotted to the design and implementation,
and 10% to the design extensions. Of the 90%, 30% will be allotted to
the command grammar and state machine model, 40% to the code
(half for structure and half for correctness), and 20% to test cases.
Defining a conversation. Part of your job is to determine what
a conversation means. For example, does a conversation have a name,
and can other users join the conversation by specifying the name? Is
it like a chat room, that people can enter and exit? In that case, can
a conversation be empty (a chatroom can), waiting for users?
Or is a conversation more like a phone call, where a person "dials"
another person? In that case, can the receiving party deny the
conversation?
However you define a conversation, remember to keep it simple
for your first iteration. You can always extend your program with
interesting ideas if you have time left.
Handling multiple clients. Since instant messaging is useless without
at least two people, your server must be able to handle multiple clients
connected at the same time. The Friendly server you'll develop in the
lab gives you some starting code, but note that
Friendly doesn't need its clients to interact or share any state. Your server
will certainly need to do that. One reasonable design approach follows the
Friendly model (using one thread for reading input from each client) but adds
a central state machine representing the state of the server (using one more
thread, to which each of the client threads pass messages through a shared
queue).
Designing for safe concurrency. In general, making an argument that
an implementation is free of concurrency bugs (like race conditions and
deadlocks) is very difficult and error-prone. The best strategy therefore
is to design your program to allow a very simple argument, by limiting
your use of concurrency and especially avoiding shared state wherever
possible. For example, one approach is to use concurrency only for
reading sockets, and to make the rest of the design single-threaded.
Designing for testability. To make it possible to write unit tests
without having to open socket connections and parse streams of responses,
you should design your state machine(s) in such a way that they can be driven
directly by a unit test -- either by calling methods, or by putting messages
into a queue read by the state machine's thread.