A7 - Unreliable Chat Client#
850 pointsRun the server
# First, install the server (only required once) ~/.local/bin/uv pip install https://compnet2526.atlarge-research.com/pip/framework-0.2.0-py3-none-any.whl # Second, run the server unreliable-serverBy default, the server will run in reliable mode, i.e., no bit flips, bursts, delays, or packet drops will occur. To enable unreliable features, experiment with the options below. A more detailed description of the unreliable features can be found in the Unreliability section.
usage: unreliable-server [-h] [-a ADDRESS] [-p PORT] [-s SEED] [-b BURST] [-f FLIP] [-pb PROBABILITY] [-d DELAY] [--scenario SCENARIO] [-v] A UDP server that simulates unreliable network conditions for testing purposes. options: -h, --help show this help message and exit -a ADDRESS, --address ADDRESS Set server address -p PORT, --port PORT Set server port -s SEED, --seed SEED Set random seed for testing (default: random) -b BURST, --burst BURST Set the length of bursts (in bits, default: 5) -f FLIP, --flip FLIP Set the bit flip ratio (default: 0.005 as a percentage of all bits) -pb PROBABILITY, --probability PROBABILITY Set the probability that an unreliability event is triggered (default: 0.1) -d DELAY, --delay DELAY The maximum delay (in milliseconds) that can be introduced by the unreliability (default: 1500) --scenario SCENARIO Load a scenario -v, --verbose Enable verbose logging © 2026 Vrije Universiteit Amsterdam - @Large ResearchRun the client (your implementation)
python3 -m a7_unreliable_chat
Assignment (650 points)#
Your task is to implement a replica of the Transmission Control Protocol as defined in RFC 9293 to tackle possible errors encountered on an unreliable network. TCP is a very large protocol, so you will only be implementing a small set of features required to ensure reliability on our toy example.
Even though we are using an unreliable server to connect our clients, consider it an abstraction of the unreliable network running under the transport layer. In reality, when sending messages from one client to another, you must consider the connection to be a peer-to-peer connection.
.png)
The virtual peer-to-peer network interaction
The possible errors that can occur over the network are described in the Unreliability section. To handle the possible errors, you will need to keep track of sequence and acknowledgment numbers for each connection, implement a checksum algorithm for error detection, a retransmission algorithm in case an error is detected, and periodic retransmission in case an acknowledgment is not received.
Protocol#
The unreliable chat client follows a protocol similar to the regular chat client, with the significant difference being that we are now working with a binary protocol rather than a text-based protocol.
The spaces present in the protocol message formats are present for readability purposes only. In the actual message, you will not receive any additional spaces. Additionally, it is not guaranteed that the message received is encoded in UTF-8 format. Thus, you are required to extract the given parameters from a bytearray (in binary format) before decoding. For example, the message 0x01 0x06 [name] could arrive at the server in the format:
# Equivalent of the A1 protocol: HELLO-FROM daniel\n
b'\x01\x00\x06daniel'Every single packet (incoming our outgoing) will follow the following format:
- The first 1 byte represents the message type. This is equivalent to the header of chat client.
- The next 2 bytes represent the length of the payload
lenin big-endian. - The next
lenbytes represent the packet payload.
Note that sending any messages to the server must follow the format above; the server will also respond with messages following the same format.
Client-side protocol#
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].
Spaces are added between bytes and parameters for clarity.
Please note that your implementation should not embed uneeded space characters.
| Message type | Message format | Description |
|---|---|---|
| HELLO-FROM | 0x01 [length] [name] | First-handshake message. The client sends this in an attempt to log in. |
| LIST | 0x02 0x00 0x00 | Request for all currently logged-in users. Note: the length of the payload will always be 0. |
| SEND | 0x03 [payload length] [payload] | The [payload] follows the format [destination username length, 1 byte] [destination username] [message]. Send a message to [destination username]. Note that the total length of [payload] may not exceed 512 bytes. |
| LOGOUT | 0x0D 0x00 0x00 | Send a graceful request to the server for closing the client. The client should only exit after the server responds with the same packet |
Server-side protocol#
The server-side protocol represents the set of messages sent by the server to the client, as responses to requests made by the client. The client should only expect these kinds of messages to arrive and handle them properly. Message parameters have been marked as [param], matching the parameters from the client request.
| Message type | Message format | Description | Response to client message |
|---|---|---|---|
| HELLO | 0x04 [length] [name] | Second hand-shake message. The server sends this if the handshake (i.e., log-in) is successful. | HELLO-FROM |
| IN-USE | 0x05 [length] [bad username] | Sent during handshake if the user cannot log in because the chose [bad username] is already in use. | HELLO-FROM |
| BUSY | 0x06 0x00 0x00 | Sent during handshake if the user cannot log in because the maximum number of clients has been reached. | HELLO-FROM |
| LIST-OK | 0x07 [list length] [name 1],[name 2],...,[name n] | A list containing all currently logged-in users, separated by the , character. | LIST |
| SEND-OK | 0x08 0x00 0x00 | A confirmation sent to the client that an outgoing message was sent successfully. | SEND |
| BAD-DEST-USER | 0x09 [length] [bad username] | The destination user provided by [bad username] does not exist. | SEND |
| DELIVERY | 0x0A [length] [payload]⚠️ This is the only packet that may encounter unreliability. | Represents the incoming message as a result of another client using the SEND protocol message. The [payload] parameter will be of format [sender username length] [sender username] [message]. Note that bit flips / bursts will only be applied to the [message] part of the packet. | |
| BAD_RQST_HDR | 0x0B [length] [error message] | Sent if the last message received from the client contains an error in the header. | |
| BAD_RQST_BODY | 0x0C [length] [error message] | Sent if the last message received from the client contains an error in the body. | |
| LOGOUT | 0x0D 0x00 0x00 | Sent by the server as a confirmation of a graceful termination of the connection, or in case the server closes. | LOGOUT |
Unreliability#
There are only four classes of unreliable interaction that can happen over the virtual peer-to-peer connection. Each one of them will occur at a probability \(p \in [0, 1)\), defined with the --probability option in the server.
| Error Type | Description |
|---|---|
| Bit Flips | Bit flips may occur once every 256 bits at random. Namely, if a bit flip error type occurs, every 256 bits of the message will include a bit flip at a random position. For each message, a bit flip error will be triggered with a probability of \(p\). |
| Bit Burst | A bit burst will scramble all bits in a given range of \(b\) bits, defined with the --burst option in the server. A bit burst will choose a random start index to fit the range \(b\), and will scramble all of the bits in the range. For each message there is a \(p\) probability that a bit burst may occur, and a bit burst may only occur once per message. |
| Packet Drop | A packet drop has a probability of \(p\) to occur. When it does, the entire packet never leaves the server, thus never reaching its destination. |
| Packet Delay | Packets may be delayed for a random duration of \([0, d)\) where the delay \(d\) is defined with the --delay option in the server. For each message, there is a \(p\) probability that a packet delay may occur. |
Unreliability is only applied to the [message] parameter inside the [payload] of the DELIVERY packet. Thus, you do not need to worry about control packets such as 0x01 being scrambled.
The
--seedoption of the server allows you to easily reproduce runs using the same parameters in testing. Always keep track of the seed used when encountering an issue.The automated testing environment will test your code with multiple seeds to ensure correctness, but also with deterministic errors.
Specification#
The following section contains the required features for the basic part of the assignment. All requirements, apart from Reliability, are identical to A1 - Chat Client; namely, your task is to replicate the reliable client over an unreliable network.
The requirements lightly model the TCP specification as prescribed in RFC 9293. You will not have to implement the entire TCP specification (such as the TCP state machine), but rather a subset of features required to provide reliability in our toy example.
Reliability#
The most significant set of requirements are those related to your program’s network reliability. The following specification defines the expected (consistent) behavior given the network unreliability simulated by the unreliable server.
- The client must not make any assumptions about the binary protocol. It is possible that special bytes such as
0x00are present in the payload of different messages. - The client must implement reliability features only for the
0x0A(DELIVERY) message type. - The client must be able to correct all types of errors by means of error detection + retransmission or error correction within 500 milliseconds of the original message arriving.
- The client must implement sequence numbers and acknowledgment numbers in order to deal with possible missing packets, as prescribed by RFC 9293. Note that you may implement per-packet sequence numbers rather than per-byte.
- Messages received on the client must be displayed in the order they were delivered by the sending client, rather than the order they arrived from the network.
- The client must implement fragmentation. Packets sent over the network should not exceed 512 bytes in size. If a client desires to send a longer message, it must be split accordingly.
- The bytes sent as part of a
0x0A(DELIVERY) message content must not exceed 35% overhead of the actual delivered message for the maximum packet length of 512 bytes. - The client must implement (part of) the TCP state machine to keep track of expected sequence and acknowledgment numbers. The client must synchronize with peers using the 3-way SYN, SYN-ACK, ACK handshake, and 2-way FIN/ACK closure.
Client#
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.
Commands#
The client must support as user input several commands. The input must originate from stdin (standard input) and follow the specific format described below. Any input that does not match one of the formats must be ignored.
- Typing the command
!quitat any point must exit the client. No additional steps should be required to exit (e.g., Ctrl+C). - Typing the command
!whomust print a list of users. - An authenticated user should be able to send messages to other authanticated users by using the command
@[username] [message], replacing the two parameters accordingly.
Technical#
We define several technical requirements serving as a qualitative standard for your implementation. We acknowledge that several implementations may work or be correct, however, to facilitate your learning process, we limit the accepted correct implementations to a subset solely making use of basic interfaces.
- The client must use the UDP transport layer protocol for all network communication. For this, you will be using the Python socket interface. Using any other libraries for network communcations is not allowed.
- The client must not use the
sendall()orexit()Python functions. - The client must not print incomplete messages.
- The client must support the sending and receiving of messages of any nonzero length.
- Awaiting user keyboard input should not prevent newly incoming messages from being displayed.
- Receiving any protocol header from the server at any point in the client’s lifetime must be handled appropriately.
- 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 provided protocol.
- The client must inform the server about exit attempts, and maintain execution until the server responds with a LOGOUT packet.
- The client must be able to recover conversations with a peer after they relogged and lost all TCP state.
Interface#
The application must print messages to stdout (standard output) and follow a strict format. Failing to meet the exact format described below will result in failing the automated testing.
Make sure to pay close attention to spaces, punctuation and commas. Some automated tests may fail if the messages do not include spaces that may be deemed redundant.
| Interface Type | Format |
|---|---|
| Prompt for authentication. | Welcome to Chat Client. Enter your login: |
| Successful authentication. | Successfully logged in as [username]! |
| Username already in use detected during authentication. | Cannot log in as [username]. That username is already in use. |
| Illegal characters detected in name during authentication. | Cannot log in as [username]. That username contains disallowed characters. |
| Server is full error encountered during authentication. | Cannot log in. The server is full! |
| Message sent to another user successfully, after executing the corresponding command. | The message was sent successfully |
| Message failed to send due to the destination user not existing. | The destination '[username]' user does not exist |
| Incoming message from another user. | From [username]: [message] |
Result of a successful execution of the !who command. | There are [user count] online users: followed by one [username] per line |
| Server detected an unknown error in the previous message’s header. | Error: Unknown issue in previous message header. |
| Server detected an unknown error in the previous message’s body. | Error: Unknown issue in previous message body. |
| Server detected a known error in the previous message’s header. | Error: The following issue was detected in your previous message body: [error] |
| Server detected an known error in the previous message’s body. | Error: The following issue was detected in your previous message header: [error] |
Bonus (200 points)#
The bonus assignment consists of two parts. Both parts must be completed to obtain the 200 points.
Part 1 - Piggybacking and Sliding Window Protocol#
Implement the sliding window protocol to allow for multiple messages to be in-flight at the same time, and piggyback acknowledgment numbers on outgoing messages. This will allow you to optimize the number of messages sent over the network, and thus reduce the impact of packet drops and delays.
To pass this part of the bonus, you must implement a sliding window protocol with a window size of at least 4, and piggyback acknowledgment numbers on outgoing messages. You must also implement a timeout mechanism to retransmit messages that have not been acknowledged within a certain time frame.
Part 2 - Max Overhead#
Using Hamming codes might increase the number of bytes you have to include to provide error correction. Your task is to optimize your protocol to utilize at most 10% overhead of the actual delivered message for the maximum packet length of 512 bytes.
It might be useful to consider smaller integer sizes, unsigned integer interpretation, and other binary tricks to reduce the number of bytes needed to provide error correction and detection. Clearly define your protocol’s header overhead before continuing with this task.