You may write the program in any language that is supported under any Integrated Development Environment (IDE). Keep in mind that available controls, objects, libraries, et cetera, may make some of these tasks easier in one language than in another.
This lab is intended to be built upon Lab 1. While it is not required that you reuse code from the first lab, most of the framework needed to implement this program should already be in place upon completing Lab 1.
All components should be managed with a simple GUI. The GUI should provide a way to kill the process without using the 'exit' button on the window.
You will implement an asynchronous message service consisting of a server process and three clients. Each client process will connect to the server over a socket. The server should be able to handle all three clients concurrently.
Clients will prompt the user for a username. When a client connects to the server, its username should be displayed by the server in real time. Two or more clients may not use the same username simultaneously. Should the server detect a concurrent conflict in username, the client's connection should be rejected, and the clients user should be prompted to input a different name.
The server will keep a cumulative log of previously used usernames and display those names on its GUI. The server should indicate which of those usernames represent clients presently connected to the server and which are not connected. Clients may reuse usernames and a client reusing an extant username should not be treated as a duplicate in the log.
When the server encounters a new username, a unique message queue should be created for that username. This queue may consist of any type of data structure, but an independent queue should exist for each name. This queue must be able to contain an arbitrary number of messages.
When a message is received by the server, the server should place the message in the corresponding queue for that intended recipient and mark that message with the time of its reception. Queues should be persistent (e.g., the contents should survive the server process restarting) even if there are no messages in that queue when the server process is killed.
When a client connects to the server, the user should be prompted to select one of two options:
If the user selects "Send message", the server should provide the log of usernames to the client. The user will then be prompted to select from one of three options:
If a user selects options 1 or 2, it is the developer's discretion with regards to how the user indicates their selection. If the user indicates their selection by typing a string, the client should reject that string if it does not match an entry in the list received from the server.
Once the user has selected the intended recipient(s), the user should be prompted to enter a brief text message. When the user has finished, the text message should be uploaded to the server.
If the user selects "Check for messages", the server should deliver the contents of the message queue that corresponds to that client's present username. If the queue is currently empty, the user should be notified that no messages are available. Once messages are retrieved by the client, the server should delete them from the queue.
The client should remain connected to the server until manually disconnected by the user. The required actions are summarized below.
Startup:
Sending Messages:
Checking Messages:
The server should support three concurrently connected clients. A cumulative log of all previously used usernames should be maintained by the server and presented on the server's GUI. The server should indicate which of those usernames (if any) represent currently connected clients. The server will execute the following sequence of steps:
The server will proceed according to whether the client wants to send or check for messages.
Notes: