Question: Step 4 : Pipelined reliability If you've made it this far, you've already built a reliable sender out of an unreliable network! Your task in

Step 4: Pipelined reliability
If you've made it this far, you've already built a reliable sender out of an unreliable network! Your task in this step is to make this sender more efficient while still being reliable. Further, you will implement selective repeat through cumulative acknowledgments.
The first step to implement pipelining with selective repeat is to ask the receiver to buffer out-of-order data so that the sender does not need to resend all data after a packet loss. The receiver-side functionality needed for this is already available: just invoke the receiver in the following way (you may include any additional flags you need for the intended loss behaviors):
python3 receiver.py --ooo_enabled
Proceed to implement the pipelined sender with the following additional steps.
(Step 4.1) Transmit a window of packets first. When transmission begins, use the function transmit_entire_window_from() to send a burst of packets starting from the current left edge of the window, win_left_edge.
(Step 4.2) Preliminaries It helps to initialize and maintain a variable last_acked that tracks the highest cumulative ACK number received so far. (Recall that you can retrieve the ACK number from an ACK through the . ack member of a Msg object.)
It also helps to separately initialize and maintain the first sequence number that must be transmitted by the sender after a number of previous transmissions. Let's call this value first_to_tx. After each transmission of application data, you may use the value returned by the functions transmit_one() or transmit_entire_window_from() to set first_to_tx.
Finally, it is useful to determine what the final cumulative ACK from the receiver (i.e., after successful reception of all data) must indicate on its acknowledgment number field. The final_ack| is just INIT_SEQNO + content_len. We will use final_ack to determine when to terminate the sender.
Next, enhance your stop-and-wait implementation with these additional checks whenever you have ACKs after a recvfrom() call.
(Step 4.3) If the ACK acknowledges fresh data, slide the window forward. The slide must reflect changes to the variables corresponding to the left window edge (win_left_edge), the right window edge (win_right_edge), and the cumulative ACK number (last_acked).
(Step 4.4) Is there more data to transmit? If the window has slid forward, the sender now becomes free to transmit more data, assuming that the right edge of the window hasn't gone beyond the set of available sequence numbers to transmit (bounded by final_ack). Call the transmit_entire_window_from() function supplied with the first sequence number that must be transmitted, first_to_tx.
(Step 4.5) If there is no more fresh data, have all required ACKs been received? This can be determined by checking whether last_acked is the same as final_ack. At this point, we can terminate all transmission and reception.
If there is either more fresh data to transmit, or not all ACKs have been received, the sender should wait for ACKs (same as it did with stop-and-wait) to help slide its window forward for the subsequent transmissions or finish receiving all ACKs.
(Step 4.6) Handling timeouts. Ensure that you only transmit_one () after a timeout, since we are using selective repeat, and the receiver is buffering out-of-order data to reduce unnecessary transmissions.
In a true pipelined reliable sender, there is a distinct timeout for each sequence number in flight. However, the select () call implements a timeout on the entire socket. The distinction between a timeout per socket and a timeout per sequence number did not matter in stop-and-wait, because all sequence numbers in flight will either be ACKed together or none of those sequence numbers will be ACKed at all. However, with pipelined reliability, if you use a select () call as you did in step 3.1, a single lost packet may not trigger a retransmission timeout on the socket if the sender is continuing to receive any data at all (usually duplicate ACKs) on the socket.
In this project, we will keep things simple and just implement a single RTO on the socket rather than one RTO per sequence number. So, you can keep the select () implementation from step 3.1.
(Step 4.7) Test your code. Your code should continue to run correctly with all the test cases in step 3.2. In addition, you can test multiple window sizes. We suggest testing with three values, the default (20 bytes), one medium (200 bytes), and one large (2000 bytes). You can change the sender's window size using the --winsize flag. A correct pipelined sender should clearly run faster than the corresponding stop-and-wait sender.
Step 4 : Pipelined reliability If you've made it

Step by Step Solution

There are 3 Steps involved in it

1 Expert Approved Answer
Step: 1 Unlock blur-text-image
Question Has Been Solved by an Expert!

Get step-by-step solutions from verified subject matter experts

Step: 2 Unlock
Step: 3 Unlock

Students Have Also Explored These Related Programming Questions!