prev next

Project 2 - Design

Overview

There are three parts to the chat system: a name service, a chat server, and a chat application.

The Name Service

The name service runs continuously on a server machine and allows users to register with it and find out others who have registered with it.  The name service keeps an up-to-date collection of registered "handles" and broadcasts this collection at regular intervals to interested listeners.  A chat server object that wishes to be registered with the name service must obtain a "ticket" from the name service.  In order to keep this ticket valid, the network chat server must continually renew this ticket.  If it fails to renew the ticket, the name service will drop its registration.

The name service will be running continuously on holly and you can count on it being running for your testing.  The protocol used by the name service is private. The only access to the name service is through the ChatServer interface.

The name service maintains a log that describes what names have been registered and what names have been dropped.  You can view the log by clicking here. Note that this file may get to be very big as more and more people work on their project.

Chat Server

The chat server provides the functionality required to communicate with the name service, to initiate chat sessions, and to be notified of incoming chat requests.  The ChatServer interface defines the behavior provided by a chat server.  A chat server will use the name service to register a handle, and to be notified when the list of registered users changes.  Since everyone is sharing the same name service, applications will be able to see and communicate with applications written by different people on different machines.

Applications can register a listener with the chat server to receive notifications of registered users and connection attempts from other applications. The chat server also provides mechanisms for initiating and accepting connections between chat applications. All network streams are managed by the chat server.

The Chat Application

The chat application is an application program with a graphical user interface that allows users to register with the name service, discover who else is registered, propose connections with other users, accept connections from other users, and chat with other users through connections that have been both proposed and accepted.

Part of the graphical user interface is a continuously updated display of the handles of the other registered users. Another part of the graphical user interface allows the user to discover proposed connections and accept them if desired. Also, means are provided so that connections can be proposed to any registered user at any time.

Multiple conversations may be established and used simultaneously through the user interface and connections can be closed at any time under control of the user.

Chat Bot System

Adam Strong has written several "bots" that you can use to test the functionality of your client. There is a bot called "EchoBot" which will echo everything you send to it, back to you. There is also a "ChatBot" which can take interactive commands from you that can initiate a chat session with your client, disconnect, etc. The information you send to these bots can be retrieved by going to the directory of your handle underneath here. Keep in mind that everything you send to the bots can be publicly viewed by everyone.

Program Structure

The Name Service

Although the name service code is being provided to you (i.e., you do not have to write it), it is important that you understand its role in this system in order to build your program.  The name service runs on holly and the actual server and port of this server are defined in the variables NetworkChatServer.DEFAULT_NS_HOST and NetworkChatServer.DEFAULT_NS_PORT.  The name service maintains a collection of registered handles and manages the renewal process so that handles that are not periodically renewed are dropped from the collection.  It also broadcasts to all interested registered users the contents of this collection at periodic intervals.  It also accepts handle registrations from remote clients and adds them to the collection.

The protocol between the name service and its clients is private and is implemented by an object that implements the ChatServer interface. You must use this interface to access the name service.

The NetworkChatServer

The NetworkChatServer class implements the ChatServer interface and provides a means for clients to access the name service and to establish connections with other chat applications.  This class will handle registration and the automatic re-registration of your handle.  As the class name implies, this class uses a network connection to establish chat sessions  This code has been written for you and is being provided for you as part of this project.

Calling the constructor for the NetworkChatServer starts the NetworkChatServer running.  If the NetworkChatServer is unable to "find" the machine on which the name service is running (by default, holly.cs.rit.edu), then it will throw a java.net.UnknownHostException, which you should be prepared to deal with.  (This may happen if you are running your program behind certain types of firewalls at home/work, or if your/holly's connection to the Internet is down.)

Once the NetworkChatServer is started and enabled, it will deliver regular events if you register a listener with it.  A ChatListener receives notifications of the currently registered handles and notifications of chat requests directed at your handle (if you have registered one).  You must enable the NetworkChatServer to receive user notifications and chat requests.

The handle that you register with the name service will be published to all registered clients of the name service.  A handle is a Java string which must be unique.  In other words no other application can register the same handle that you are using, while you are actively using it.  If it is not unique the server will refuse to register the handle.

Once you have registered a handle with the NetworkChatServer you may attempt to chat with another registered user (even yourself) or accept a connection from another user.  No communication is possible until a connection is proposed and accepted.  It is possible to set up several distinct connections with the same user.

The ChatSession Object

Once a connection is both proposed and accepted, both ends of the connection will obtain a reference to a ChatSession object whose state describes the connection.  Specifically, the ChatSession object will maintain a reference to a Reader and a Writer that can be used to receive and send character-based data across the chat connection.  Anything written to the Writer on one end of a connection can be read with the Reader at the other end of the connection.  It is the responsibility of the chat application to appropriately read and write these streams so that meaningful communication can be accomplished.  All chat applications should be capable of dealing with plain text and exchanging data with other chat applications on a line-by-line basis (i.e., reading/writing a full line of text at a time), although other formats might be supported.

Closing the ChatSession object closes both the Reader and Writer associated with it.  If one end of the connection is closed, any attempts to use the other end will result in an IOException being thrown.

Use of the Server

Listed below are some typical interactions that a chat application program might have with the server.

Register with the server

  1. Create a new NetworkChatServer.
  2. Add a ChatListener to receive notifications of registered users and connection attempts.
  3. Enable the server to enable connection attempts.
  4. Register a handle with the server for others to see.

Initiating a connection

  1. Invoke chat(handle) to propose a connection with user handle.
  2. Use the ChatSession object returned in step 1 to obtain a a Reader and a Writer for communicating with the other user.
  3. When done, or when the Reader or Writer is closed from the other end, close the session object.

Accepting a connection

  1. When a notification of a connection attempt is received by the ChatListener, you will receive a ChatSession object.
  2. The ChatListener will need to invoke the accept() method on the ChatSession object in order to signal to the ChatServer that the connection request has been accepted by the user (if appropriate).
  3. The ChatSession object may then be used to obtain a Reader and Writer for communicating with the other user.
  4. When done, or when the Reader or Writer is closed from the other end, close the session object.

The Chat Application

The chat application you will write will be started from the command line with a single "handle" argument.  Unless there are errors, the application will bring up a graphical user interface and all further interaction with the application will be through the GUI.  No messages will be printed to System.out and no data will be read from System.in.  The GUI will continuously display the currently registered handles.  The user will have the ability to initiate connections with other users and accept or reject connections proposed by other users.  If a connection is made with another user, then the application will provide a means of interacting with this other user.  Multiple connections with other users should be possible simultaneously.  There should also be the ability to close any open connection without affecting other connections, as well as a means of shutting down the entire application.

The user receiving a request to chat should be given the opportunity to either:

  1. Accept the incoming request, in which case a ChatListener must invoke the accept method on the ChatSession object provided by the server, and then provide the GUI to support an interactive chat.
  2. Deny the request, in which case a ChatListener should explicitly close the channel to the other user by invoking the close method on the ChatSession object. (Note: you may want to accept the chat for the sole purpose of sending a message to the other user that says something like, "No, I really don't want to talk to you right now" on a separate thread before closing the session.)
  3. Ignore the request, in which case none of your ChatListener objects should invoke the accept and close methods on the ChatSession instance that they receive from the server.

Since many things are happening simultaneously and some things might take a long time, the application should start separate threads for any operation that might be delayed.  In particular, you should not do opens, reads, or writes in a listener thread (either a window listener or a ChatListener) but rather create a new thread to do the work.


prev next
version 1.26, 2007/02/06 16:43:44, © by csfac@RIT. All rights reserved.