Implementation Details - sid4/reliableUDP GitHub Wiki
The sender header consists of sequence-no delimiter data. The sequence no. occupies the first 6 bytes of the header. Next 1 byte is occupied by the delimiter “;”. Finally up to next 1000 bytes can be occupied by the payload/data. The sequence no wraps around after 99,998.
The Server is implemented with four threads. There is a main thread (which is always running) which creates the socket and listens to requests. On receipt of a valid request, the main thread creates three threads:
-
Writer Thread: This thread reads the chunks from the requested file and writes it to the socket
-
Receiver thread: This thread receives the acknowledgement from the receiver/client
-
Timeout Thread: This thread continuously checks for any timeouts
The above three threads work on a shared data structure (struct log_store), which acts like a log book with a size limit (which also acts as our effective window at any point of time). The insert_arr() function acts as the sole interface for insertion into this data structure. This method only allows insertion when there is enough space in the effective window(which is the size attribute/member of the struct). The resize_log_store() function aids in re-sizing the size of the underlying logs store.
It reads a chunk of data from the requested file and then tries to insert a log of it into the shared data structure. This chunk of data is not written to socket until insertion is successful. This means, in case the effective window is full, then the chunk has to wait for acknowledgments to arrive or in other words until there is a slot in effective window.
As soon as the receiver thread receives the ack from the client, it deletes the log from the shared data structure and manipulates the effective window according to its current mode (which will be slow start or congestion avoidance or fast recovery) and also transitions to a different mode if applicable. Rules applied for transition of state/congestion control are same as depicted in FSM of figure 3.5.2, page 275, course book.
In case three duplicate acknowledgments are received, it sends the packet with (ack-1) sequence no., updates its timestamp in logs, indicates resend and also enters in fast recovery mode.
On receipt of every ack of a non-timed out or a non re-sent packet, the devRTT, estimatedRTT and timeout is calculated according to Jacobson/Karel's algorithm (adaptive re-transmission).
The timeout thread continuously keeps on monitoring the logs or packets sent. At any point of time, a packet with time stamp older than the current timeout limit is detected, it re transmits it and also updates the time stamp of it in the logs, as well as indicates the resent status.
After writer thread completes writing all the data to the socket, it exits. After it exits, receiver thread stays alive for almost a minute, after which it also exits. After exit of reader thread, timeout thread stays alive for almost a minute, after which it also exits. Cumulative stats are printed on the screen and the server is made ready to accept new requests.
The messages sent by client consists of . The ack. no. occupies the only available 6 bytes of the header.
The client is implemented with single thread. Client sends the desired file name (it is assumed, it exists on the server) to the server. After which client starts receiving packets from the server. The client only accepts the packets which are in order. For every in-order packet it sends, (recived packet sequence no.+1) as the ack and for every out of order packet, it sends the ack last sent for in-order packet. Also it is to be noted, the client sends selective acknowledgments (not cummulative) for packets received in-order and duplicate acknowledgments for out of order packets.
For simulating variable packet loss, the client simply doesn't send an ack for the packet it wants to show as being lost. The decision for which packet is to be dropped is made by the dropPacket() function, which uses the current time and the value given by the user to problematically drop the packet. It is implemented as, if mod ==0, drop the packet.
For simulating high latency, the client sends the ack after the delay specified by the user at command line in ms. This delay is introduced by making the thread sleep for user specified time before sending the ack.
The client assumes there is no more data to receive after 2 minutes have elapsed since the last receipt of packet. At termination clients prints out the stat of the whole transmission.