You will be created a socket client/server program that implements a shared drawing canvas. Clients will connect to a multithreaded socket server that keeps track of the lines drawn by all the clients. The clients will see (after a short time delay anyway) all the lines drawn by everyone. Any client can also clear all the lines.
Getting started. You will developing a few simple classes as well as the main programs for the socket client and the multi-threaded socket server. There is no stub code for this assignment. We have given you the API for the two simple classes. The client and server programs you can base off some of the socket examples given in class.
Line. It doesn't get much simpler than this. A Line object represents a two-dimensional line with a given color. It knows things like its end points and its color. It can do things like return a string representation of itself and draw itself. Your Line data type must implement the following API:
public class Line
Line(double x0, double y0, double x1, double y1, int r, int g, int b) // Create a line (x0,y0)-(x1,y1) with RGB(r,g,b)
String toString() // String representation of the line, format "x0 y0 x1 y1 r g b"
void draw() // Draw the line using StdDraw
Lines. The Lines class main job is to store a collection of Line objects. This class is also important as it controls access to the shared data being assessed by the server's worker threads. Hint: think carefully about what methods need to be synchronized in the API. In your multi-threaded server, a single Lines object should be used by all the worker threads. Here is the API:
public class Lines
void add(Line line) // Add a new line to the collection
String toString() // Return a single line containing the data for all the lines
int size() // Find out how many lines are currently in the collection
void clear() // Remove all lines from the collection
Communication protocol. Before discussing the other classes you'll implement, it is important to understand the communication protocol between the client and server. The client and server communication using a simple text-based protocol. The client always initiates a communication by sending a single line of text to the server. Normally the line is only the command, but in the case of the ADD command, additional parameters specifying the location and color of a line follow the command word. After receiving a command from the client, the server does the appropriate action and sends a single line of text in response.
The following tables details each command: See image.
LineClient. This is the program that does the actual drawing shown in the video. The client program should periodically (e.g. every 100ms) execute a GET command to obtain the current set of lines and the number of clients currently connected. The number of lines in the shared canvas should appear as text in the upper-left corner of your window. The current number of clients connected should appear as text just below the count of lines.
The client program takes two optional command line arguments, the first is the hostname of server. The default hostname should be "localhost". If the hostname is present, a second optional command line argument may also be accepted. This is the port number of the server. The default value of the port should be 5000.
When a client starts, it chooses a random RGB color. All lines drawn by the same client are always this same random color for the lifetime of the client. The start position of a line is indicated by the user pressing the mouse button. The end position of that line is when the user releases the button. After button release, an ADD command is sent to the server to add the new line to the collection. As shown in the video, you don't need to draw the line until the button is released. New lines drawn by other clients should continue to appear even while a client is busy drawing a line (i.e. the user has the mouse button pushed).
The client program supports two commands via the keyboard. The 'q' key causes the client to execute the QUIT command to cause orderly closing of the input and output streams as well as the socket. Note that the drawing window in StdDraw remains open even after your client's main() method finishes. The 'c' key causes the client to execute a CLEAR command. This removes all lines from the shared set stored on the server.
LineServer. This program has only a main() method and takes a single command line argument, the integer port number to listen on. The program's job is the spawn the worker thread to handle an incoming client and then carrying on listening for new clients. It is similar to my ValueServer.java and Magic8ServerMulti.java examples.
LineServerWorker. This is the server-side workhorse. The worker needs to have access to the Lines object so it can add new lines or clear all the lines if a client requests it. The class also keeps track of the total number of clients. The worker waits for a single line of text from the client and always responds with a single line.
The worker should print out some information to the console when clients connect or disconnect. When a client connects, print out "HELLO:" followed by the client's Socket object. Then print another line "CONNECTIONS:" followed by the total clients connected once the new client joins.
If the worker receives a QUIT command, it response with "OK" and then does an orderly closing of the read/write streams and the socket. When the client disconnects, print out "GOODBYE:" followed by the client's Socket object. Then print another line "CONNECTIONS:" followed by the total clients connected once the new client joins.
The client may be naughty and shutdown without sending a QUIT command. Try this and see what happens to your worker thread. Handle this circumstance so that your worker prints out "HANGUP:" followed by the socket information, updates the client counter, and then displays the number of connections after the impolite client is gone.