We have seen that UDP is not a reliable transport protocol. Now, we will look at the TCP protocol which is reliable. TCP is a very complex protocol. We will look at the ideas behind at, but it is a large and deep topic.
A packet sent with TCP may potentially be corrupted. Like UDP, TCP packets contain checksums which are checked when a packet is received. Unlike UDP, TCP will resend packets which are corrupted.
TCP sends acknowledgement packets (ACKs) when a packet was received successfully and negative acknowledgement packets (NAKs) when one was corrupted:
When a packet is lost, it is re-transmitted until it receives the ACK message.
One issue with this, however, is that the ACK and NAK packets themselves can be corrupted!
If the sender receives a garbled response, what should it do? There are two possible approaches:
TCP takes option 2. Now the receiver needs to distinguish a new packet from a duplicate one. To do this, TCP includes a "sequence number" field with all packets. When it receives a packet, it checks if the sequence number is a new one or not.
In addition to corrupted packets, TCP handles lost packets. When a sender sends a packet, it is responsible for ensuring that the packet is received. When a packet (or the ACK for it) is lost, it must re-send the packet.
However, how can a sender know if a packet was lost or just delayed? From the sender's point of view, the only evidence of a dropped packet is the lack of an ACK for it. But maybe the ACK is on its way and just taking a while.
The sender has 2 constraints:
TCP has the sender wait long enough that packet loss is likely but not guaranteed.
TCP also handles the problem of packets received out of order. This is also handled with the sequence numbers. Whenever a packet is sent, there is a sequence number sent along with it. This sequence number starts at 0, and increments for each byte which is sent.
So if a sender wants to send a 5 kilobyte file, which gets broken into 4 packets (1500 bytes is about as big as packets get). It could then send the packets with the following sequence numbers:
When the receiver gets a packet, it will check if the sequence number is a duplicate (to avoid duplicate packets), and also use it to put the packets back into the correct order.
This is enough to give TCP the reliability that it promises. However, being reliable isn't the only goal of TCP. It also strives to be as fast as it can be. As described thus far, a sender basically will do this:
This is called a "stop and wait" protocol. Because we wait for a response after each send. The following figure depicts this:
Here the data transmissions are represented with the thicker bars. The sender only sends data after receiving a response.
A faster approach is to pipeline the transmission. This will entail sending multiple packets, one after the other, before hearing back on whether the first was received correctly or not.
Here we are pipelining by sending three packets before waiting for acknowledgement. This decreases transfer time because we can send three packets in a little less than the time to send one packet.
However it complicates the protocol somewhat. Now the receiver may receive packets 0 and 2, but not packet 1. How should it address these issues?
One approach to allowing for pipelining is the Go-Back-N (GBN) protocol. Here, we have some maximum number of packets that are allowed to be in flight at any one time.
We can send up to N packets before getting acknowledgement, but cannot go past that number. The following diagram gives an example of a GBN protocol when N is 8:
Here we have sent 5 packets that have not yet been acknowledged. Because N is 8, we can send 3 more, but cannot go past that.
The set of packets that can be in flight is sometimes called a "window". As the sender receives acknowledgement for sent packets, the window moves to the right. For this reason, GBN is referred to as a "sliding window protocol".
Below is what the sender and receiver each do:
When a NAK packet is received, or if a timeout is reached, the sender will resend the packet in question, and all subsequent packets. When an ACK is received, the window slides forward and the sender sends a new packet of data.
When packets are received successfully, we send back an ACK for the most recently received packet only. For instance, if we receive 8 packets, we will only send an ACK for #8. This tells the sender we got them all and it can move along.
Another way of implementing pipelining is called selective repeat. It aims to avoid resending packets unnecessarily, as GBN sometimes will. In order to do this, the receiver sends ACKs for each packet individually, whether it is in order or not.
The sender must keep track of the status of each packet in the window individually. If one needs to be resent, it can resend only that one. Hence the name "selective repeat".
The sender/receiver operation is outlined below:
When a NAK packet is received, or if a timeout is reached, the sender will resend just the packet in question. When an ACK is received, we mark that packet has being acknowledged. If that was the oldest unacknowledged packet, then slide the window 1 to the right.
When packets are received successfully, we send back an ACK for that packet. For instance, if we receive 8 packets, we will acknowledge all 8.
What are the trade-offs between the two protocols?
TCP actually uses sort of a hybrid of these two schemes. Like GBN, it allows the receiver to acknowledge multiple packets at once. However, like SR, it allows the receiver to request the resending of specific packets, in any order.
Below is a diagram of a TCP packet:
The fields are described below:
Copyright © 2021 Ian Finlayson | Licensed under a Creative Commons Attribution 4.0 International License.