A1 - Chat Client
Last updated
Last updated
In this assignment, you implement a text-based chat client. You use Python, sockets, and the Transmission Control Protocol (TCP) for this. Once you are comfortable using the socket interface, using sockets in other programming languages should be straightforward.
The chat client and chat server are built on top of TCP and use their application-layer protocol. This means the client and server can request the other to perform actions by sending predefined types of messages. For example, your client can ask the server to forward a message to another user’s client by sending the string SEND [username] insert your message here
to the server, where [username]
is the user to whom you want to send your message. If your message is correct, the server will send two messages: one to the destination user, forwarding your message, and one back to you that says SEND-OK
, to notify you that your message was forwarded successfully. Keep in mind that these messages can be of any length. Therefore, you need to make sure that your client can handle arbitrary message lengths.
Similar to Web browsers and other modern applications, your chat client does not expose the protocol it uses to the user. Instead, it provides a user-friendly text-based interface that makes it easy for users to chat with others without knowing the protocol specifications. The specifications of this interface, and the requirements of this assignment, are listed below. For automated tests, we require your chat client to precisely follow a pre-defined text interface.
All application-layer software must implement a pre-established protocol for communicating over the network. Application-layer protocols are simply conventions for methods of communcation. Some popular examples of such protocols for chat clients are the and protocols.
In our simplified example, we propose a simplified, text-based protocol. Compared to other protocols, ours does not prioritize space efficiency by encoding message types in bytes, but rather focuses on developer experience. This is why the proposed protocol uses strings for the message headers and contents.
All protocols must define some form of convention for ending a message. Possible solutions include embedding the length of the message in the first few bytes or reserving a set of characters to mark the end of the message.
In our protocol, we delimit the end of the message by using the newline (\n
) character. Thus, you should always make sure you have received everything until the end of the message before proceeding to processing.
The client-side protocol represents the set of messages sent by the client to the server. The client shall never expect any of the following messages to come from the server. Message parameters have been marked as [param]
.
HELLO-FROM [name]\n
First hand-shake message. The client sends this in an attempt to log in.
LIST\n
Request for all currently logged-in users.
SEND [name] [message]\n
Send a chat message for a user with username name
. Note that the message cannot contain the newline character, because it is used as the message delimiter
The motivation for using specifications is given by the need for reproducible implementations. Namely, we would like different implementations (perhaps in different programming languages, supporting different architecture) to be able to interact with all other implementations.
In our chat client, we will use a simplified specification defining the functionality of a terminal user interface (TUI) application.
The client requirements define the general functionality the program should implement. The technical details are covered in the Technical tab. Please note that your application must follow a strict textual interface, which is defined in the Interface tab.
The client must ask the user for a username and attempt to log them in.
The client must ask the user for a new username if the provided one is already in use, with an informative message.
The client must inform the user if the server is full and exit gracefully.
The client must inform the user if their username was rejected for any other reason and ask for a new username. The list of forbidden characters in the username is !@#$%^&*,
and spaces.
The client must inform the user if their username was rejected for any other reason and ask for a new username. Examples include commands (@username, !who)
The client should not have to be restarted after a failed log-in attempt.
The client must be able to send messages to other authenticated users.
The client must be able to list all logged in users.
The client should only respond to messages received from the server. Specifically, the client should not store any state other than the connection's socket.
To test your implementation, you should run the local server and connect to it using multiple clients. To run the local server, open up a new terminal and execute:
Developing application-layer software usually implies implementing functionality baed on a set of requirements. The set of all requirements that define the implementation is called a specification. The state-of-art for software specifications is , which you will use for some of the extra assignments.
The client must support as user input several commands. The input must originate from stdin () and follow the specific format described below. Any input that does not match one of the formats must be ignored.
The client must use the TCP transport layer protocol for all network communication. For this, you will be using the Python interface. Using any other libraries for network communcations is not allowed.
Your implementation must not make any assumptions about the data received from the network. The only specification that should be followed is that of the .
The application must print messages to stdout () and follow a strict format. Failing to meet the exact format described below will result in failing the automated testing.
If successful, you should be promted with a message similar to [2025-04-11 01:59:43,489 - INFO] Server listening on 0.0.0.0:5378
. If this failed, you probably forgot to enable the conda environment. You can check this by verifying that the (computer-networks-lab)
prefix exists at the beginning of your prompt. Please consult the section to learn how to enable the conda environment.
Once started, the server must remain open to listen for incoming connections. The recommended approach to developing the chat client is to open up two or more separate terminals and run the client in each of them. Then, attempt to send messages between users. Additionally, you may use the command to debug different messages incoming from the server.
Finally, once every requirement from the is met, you may submit your code to CodeGrade for automated testing.