Theory: Transport Layer#

The networking layer routed packets of data across the Internet to their final destination. But how do we know the data got there? That someone was listening? What if we have more data than we can fit in one packet? What if there is an error and we need to resend the data? How do we manage all that, and still transfer our data as fast as possible? This is the responsibility of the fourth layer of the OSI model, the transport layer.

The transport layer ensures the large web pages, video files, and documents get broken into packets of manageable size, transmitted, and reassembled by the receiver. The first transport protocol we’ll learn about is the Transmission Control Protocol (TCP). Web page requests, documents, messages, almost all data on the Internet is transmitted through a TCP connection. There are additional transport protocols that are built on top of TCP. The web uses HTTP, email both SMTP and IMAP, and file transfers use FTP.

If you plan on managing networks, creating networked programs, or be a technical manager, understanding these how these transport protocols is necessary to keep networks up, add functionality to your programs, and collaborate with your coworkers.

TCP Connections#

As networks have standardized on TCP/IP, this is the place to start for learning how to transport large files across the internet. You can use everything you learn here and expand on it to understand how we transport data for the web, email, and files.

To learn TCP, you’ll first need to understand how to open a connection. After the connection is open, we’ll learn how to move data, and confirm its safe arrival. Finally, when done, you’ll need to close the network connection.

Create a Connection – TCP Handshake#

Before you pass data over a TCP connection, you must set up the connection. With TCP, this is a three-step process as shown in Fig. 93.

First, the client that wants to create a connection generates a TCP synchronize packet (SYN) and sends it to the server. The SYN packet includes a randomly generated 32-bit sequence number. The sequence number identifies client-to-server data packets, so you can tell which packets have arrived. In the “sliding window” section, discussed later in this chapter, you can see the sequence number at work.

Second, the server sends back a two-in-one packet known as a synchronize acknowledgement packet (SYN-ACK). It acknowledges the client’s SYN packet and combines this acknowledgement with a SYN packet of our own. Data sent from the server-to-client gets a completely different sequence number to clearly identify packets of data traveling in the opposite direction, from the client back to the server. Therefore, our TCP connection will track two different sequence numbers.

Finally the client sends an ACK back to the server to let the server know its SYN-ACK packet was received. The connection is now established.

TCP Handshake for opening a new connection

Fig. 93 TCP Handshake for opening a new connection#

ACK Packets and Sliding Windows#

The transport layer’s job is to offer reliable transmission of data in the same order it was sent. The networking layer can lose packets, and it is up to the transport layer to find the missing data and ask for it again. In addition, packets can occasionally travel the network using different routes and arrive out-of-order. The transport layer must be able to handle that possibility by either reordering the packets, or resending them.

The simplest method to address these problems is to send an acknowledgment packet (ACK) each time you receive data. As shown in Fig. 94, each time a packet is sent, you wait for an ACK. For simplicity, this example uses a sequence number that alternates between 0 and 1.

Using ACK Packets

Fig. 94 Using ACK Packets#

What happens if the data doesn’t arrive? Fig. 95 shows that if the data packet doesn’t arrive, eventually the sender will time out waiting for the ACK, and resend the data. The longer the timeout, the slower it takes to recognize we are missing a packet and start transmitting data again. If the timeout is too short, however, the computer might resend data unnecessarily, thinking the data was lost.

The timeout calculation for TCP depends on the average round trip time and the amount keeps doubling for each successive timeout. In fact, TCP can wait about ten to thirty minutes before completely giving up on a connection after about fifteen retries.

If instead the ACK gets lost, the sender will still time out and resend the data. The data packets need the ACK sequence number, so the receiver can identify when a duplicate packet arrives that needs to be discarded. We don’t want to add duplicate data to the receive buffer.

Losing Packets

Fig. 95 (left) Data Packet Loss (right) ACK Loss#

This protocol ensures that your data gets to its destination. But you can’t transfer data very fast this way. Remember doing ping times from the tutorial on networking tools in Chapter 7? It often takes more than 10 ms to get to another computer and receive the acknowledgement. At that rate you could exchange 100 packets per second. If each packet is limited to around 1500 bytes of an Ethernet frame, that makes for 150 kilobytes/second (kB/s) or 1.2 megabits per second (Mbps). It would take about seven seconds to download a one-megabyte image on a web page, just because of how long it takes to acknowledge the data packets.

Remember, there are eight bits to a byte. You abbreviate byte with a capital B, and bit with a small b. So Mbps is always eight times the value of MBps. One MBps equals eight Mbps.

With this approach, you are spending most of your time waiting for packets and not enough time transmitting data. How can you improve this? Since it is not common for a network to lose packets, you can send multiple packets and use additional sequence numbers, as shown in Fig. 96. When you have received Data 1, you send an ACK 2 showing you are ready for Data 2 and that everything up to, but not including Data 2 has been received ok.

Two Packets Per ACK

Fig. 96 Two Packets Per ACK#

This approach is better, but a delay still happens as the computer waits for ACK packets. What if the code behind the transport layer did not wait? Compare Fig. 96 with Fig. 97, where the system does not wait for the ACK on data packet 0 and data packet 1, but continues to transmit data packets 2 and 3. While there is still a round-trip delay, we no longer wait for it.

Two Packets Per ACK

Fig. 97 Overlapping ACK and Data Packets#

This method requires a bit more work on the sender, as the transport-layer code must track what part of the message has been sent, and what part acknowledged. Overlapping in this way is called a sliding window, which is illustrated in Fig. 98:

Sliding Window

Fig. 98 Sliding Window#

In Fig. 98 each packet is numbered sequentially. TCP numbers its sliding window a bit differently: that is, rather than number each packet, TCP numbers by the byte count. If the first packet is numbered 0 and you transmit 700 bytes, the next packet will be numbered 700 rather than 1. Then if you transmit 1,001 bytes, the next packet will be numbered 1,701. TCP stores the sequence number in four bytes, or \(4 \cdot 8 = 32\) bits. The maximum sequence number is \(2^{32}-1=4,294,967,295\). When you go beyond that four billion max number, you “roll over” back to zero. TCP can send both data and an ACK at the same time. In the earlier examples, data flowed only one way. It can flow both ways, and you can combine your data and ACK packets together.

One of the best ways to understand the sliding window is to view it as an animation. Johnannas Kessler has a nice interactive animation available at the link below. This animation allows you to control different parameters as well. I recommend watching the animation both with the default end-to-end delay of 5000 ms, and trying 2000 ms.

http://www.ccs-labs.org/teaching/rn/animations/gbn_sr/

The sliding window is key to unlocking the full speed of a network. Remember from the start of this section, if we wait for an ACK on each packet, have a ping time of 10 ms and packet size of 1,500 bytes, we’d be limited to 1.2 Mbps, even if we had a fast gigabit (1,000 Mbps) connection. Our data would only be transmitted at 0.1 percent of the maximum speed. That sliding window eliminates the round-trip wait and makes it possible for our video, web pages, and files to be downloaded 1,000 times faster.

Buffering and Pushing Data#

If you are writing networking code, it’s important to understand how the data is buffered up and sent, because it impacts both the timing on when data is sent, and how the data is grouped together. For example, if you executed the following networking code in Python:

my_socket.sendall(b"1")
my_socket.sendall(b"2")
my_socket.sendall(b"3")

Based on these three lines of code, there are at least two logical guesses on how the code would group the data into packets. One, the program could send three packets, each with a different number in it. Or two, the program could keep storing data until the buffer is full and then send “123” as one packet.

What happens in reality? Neither. Python will send the 1 to the transport layer. The transport layer bundles up the 1 into a packet, and the computer will start sending it. The 2 and 3 arrive immediately after, but we can’t change the packet in the middle of being sent. Therefore the transport layer will queue up the 2 and 3 into the same packet and send “23” when the network is ready again. Depending on your networking back-end, you might have different behavior. Some computer languages will queue the data until there is enough for a full packet, or until you explicitly flush the data. This can cause unexpected results, for example a line of code to send data, may not immediately send the data. Instead the code would just queue it up and only send the data once there’s a full 1,500 bytes to send. It is a good idea to experiment with simple test cases and observe with a program like Wireshark to see what happens.

In the case of the three-line example above, we can use our understanding of networks to buffer up all three numbers and send them out as one packet using one sendall command:

my_socket.sendall(b"123")

This will only transmit one packet instead of two, resulting in the entire message arriving twice as fast. Remember, moving data in one large packet is more efficient than multiple smaller packets.

Some computer languages work differently. For example, sending data with Java will put the data in a buffer, but not immediately send it. Data will be sent when the buffer is full, or when the program calls a flush() function. This can prevent the unnecessary fragmenting of our data across two packets as shown in our Python example. The disadvantage is that if we forget to flush the buffer, we might be stuck waiting for a response to data that was never sent.

The exact same thing can happen in reverse. Data received can be buffered and only passed up to the destination program once the buffer is full. For cases where we don’t want to wait, a TCP/IP packet can have a push flag (PSH) set. This tells the receiver to not wait for more data, but to go ahead immediately pass it to the receiving application.

Close a Connection#

The last step when sending data between clients and servers is closing a connection. One side will send a finalize packet (FIN), stating it will not be sending any more data, as shown in Fig. 99. This doesn’t mean you can close the connection yet! The other side may not have successfully received all of the data; it may still need to send ACK packets or request rebroadcast of any missing data. After the other side has sent all of its ACK packets, it will also send a FIN packet. That second FIN packet must be acknowledged, and then the connection can close.

Finalize connection

Fig. 99 Finalize connection#

Conclusion#

At the networking layer, we learned how to move individual packets of data across the network. Here, in the transport layer, we learned how to use those packets to set up a TCP connection to efficiently and accurately transfer larger files worth of data. We can build on those TCP connections to transport email via SMTP and web pages with HTTP. Most networking connections on the internet use the transport protocols. In the next chapter, we’ll use this theory to create TCP connections between programs. We’ll build on that to create our own program that can take a simple visualization of a bouncing ball, and have it bounce from one computer to another by using a TCP network connection.