The Transport Layer

Overview

In general, transport layer protocols provide various services on top of the network layer that make them suitable for direct use by network applications. Usually, these services are some combination of demultiplexing, reliable data transfer, and congestion control. In practice, more than 90% of the packets on the Internet are TCP packets, so we mainly focus on TCP. However, some applications instead choose to use the Unreliable Datagram Protocol (UDP), so we discuss it briefly as well.

Demultiplexing

One of the most common features provided by the transport layer protocols is called Demultiplexing. In a nutshell, demutltiplexing refers to sorting incoming packets into different sets of data according to some criterion. Demultiplexing is critical if more than one program on a computer wishes to use the Internet. If your web browser and your email program both need to receive data from the Internet at the same time, they need a mechanism to divide up incoming packets so that the browser doesn't get confused by email packets and so that the email program doesn't get confused by web page packets. TCP and UDP both provide this capability with Ports. When a program sends a TCP or UDP packet to an IP address, it specifies a port number between 1 and roughly 65,000. When the destination computer's operating system receives the packet, it delivers it only to the program that registered itself under that port. Note that while both TCP and UDP use the same notion of ports, the operating system handles each protocol separately. That is to say, there is no inherent connection between TCP port X and UDP port X.

Streams

The killer feature of TCP is that it lets programmers write software as if there were a Reliable Stream of data between two computers. In other words, TCP offers a 'pipe' into which one application can send data and rest assured that it will come out of the other end in order and intact. Moreover, the connection is full-duplex (two-way), so there are really two pipes: one going from each computer to the other. This is a great boon for programmers, because they don't need to spend very much time worrying about the details of how their data gets from one computer to another.

However, the inner workings of TCP are probably some of the most complicated among all the protocols on the Internet. This is because IP makes no promises that packets will arrive in the order they were sent or even that they will arrive at all. In order to handle this problem, TCP puts identifiers called Sequence Numbers on each packet it sends. After selecting a random starting number, TCP assigns consecutive sequence numbers to each byte of data in the stream, and labels the sequence number of the first byte of data in each packet. Thus, if a computer receives a TCP packet with 26 bytes of data starting at sequence number 4270, it knows that it has received bytes 4270 through 4295 of the stream. This helps the receiver put the data in the proper order before delivering it to the application.

Unfortunately, packets sometimes get lost. They can be corrupted during transmission between two hops, or they can be dropped by a congested router. Since TCP promises to deliver data reliably, it needs a way to cope with the possibility that not every packet makes it to the destination. While the details are sometimes more complicated, the general mechanism for this is as follows. When the starting sequence number is selected, the receiver creates a series of empty slots for the first few thousand bytes in the sequence. Whenever the receiver gets a packet of data, it checks the sequence numbers that the received bytes correspond to and puts them in the appropriate slots. Whenever the receiver has a series of bytes with no holes starting at the lowest slot, it sends those bytes off to the application and re-labels the slots to make room for higher sequence numbers.

In order to communicate its progress back to the sender, the receiver sends an Acknowledgement (ACK) packet back to the sender each time it receives data. The ACK packet indicates the sequence number of the first hole, telling the sender 'I have received everything up to here'. If a sender transmits a packet but does not get an ACK for it within a fixed amount of time, it concludes that the packet was lost and resends the data.

Congestion Control

When a a lot of data needs to be sent over the Internet, it might seem efficient for the sender to transmit at the highest possible rate. However, in the early days of the Internet, researchers realized that the Internet would quickly grind to a halt unless careful limits were imposed on the sender. If many packets arrive at a router all at once, the router has no choice but to drop some of them. This, however, triggers retransmissions by the sender, which leads to more dropped packets. If the drops occur at the 18th hop, the resources of 17 routers are wasted forwarding packets that will never arrive. Thus, the designers of TCP added a form of Congestion Control to the protocol to make TCP a better Internet citizen. A sender gradually increases its rate until it encounters a drop, at which point it halves its sending rate and continues as before.

The sender interprets the drop as a sign of congestion in the network, which may not necessarily be true: the packet could have been corrupted in transmission and discarded after a failed CRC check. However, the designers of TCP decided that this mechanism was the best way a sender could detect congestion and slow its rate. This is not to say that other, perhaps better mechanisms have not been tried. Indeed, several researchers have suggested that routers should actively tell senders to slow down when they determine that they are becoming congested. However, for various reasons, such schemes have not caught on, so TCP packet loss detection is the dominant form of congestion control on the Internet today.

The Unreliable Datagram Protocol

TCP tries, come hell or high water, to deliver every byte of data, in order, to the receiver. This is what most applications want, since losing chunks of data adds a huge amount of uncertainty to a program. However, specialized applications that push the limits of the Internet often have their own idea of what should happen when packets are lost. Take, for example, Voice over IP (VoIP) applications like Skype. Skype transmits data in real time, so there's a very small window between when voice data is received and when it is played. If a packet corresponding to a millisecond of audio goes missing, there isn't time for a retransmission. It isn't worth pausing the speech signal to wait for a retransmission, since that would only make the problem more noticeable. Moreover, if the application isn't waiting, the packet isn't worth retransmitting, since it won't arrive in time to be played. Thus, such applications require a more bare-bones protocol, and usually use the Unreliable Datagram Protocol (UDP). UDP allows applications to send and receive individual packets, providing only a demultiplexing service on top of IP. With UDP, applications that want to tame the unreliable network in their own way are free to do so.