TCP vs UDP

December 30, 2023

Overview

Background Before Comparing

TCP (Transmission Control Protocol) and UDP (User Datagram Protocol) are alternatives that sit at Layer 4 of the 7-layer OSI Model that depicts the various layers of networks. The OSI Model is the most popular model for depicting these layers. However, operationally, the functionality of these 7 layers are often handled by ~4 layers of software.



TCP/IP Model

The OSI Model is a standardized (by the International Organization for Standardization) theoretical framework of the various functions of telecommunications or computing systems without regard to its underlying internal structure and technology. The TCP/IP Model is a more practical representation of the theoretical OSI Model. The separation of layers in the TCP/IP Model demonstrates the operational distinction rather than theoretical distinction. Although the TCP/IP model is named after two specific protocols – Transmission Control Protocol (TCP) and Internet Protocol (IP) – it actually encompasses a much broader range of internet protocols. This includes not only TCP and IP but also other protocols such as UDP (User Datagram Protocol).

TCP/IP LayerOSI Model Mapping LayerHardware ExamplesSoftware Examples
1-Link Layer1-Physical + 2-Data Link LayersNetwork cables, Network Interface Cards (NIC)Ethernet protocols, NIC drivers, Media Access Control (MAC) addressing
2-Internet Layer3-Network LayerRoutersInternet Protocol (IP)
3-Transport Layer4-Transport LayerN/ATCP, UDP
4-Application Layer5-Session + 6-Presentation + 7-Application LayersN/AThe choice of application-specific protocol like HTTP/HTTPS rests in the hands of the high-level software developer. The same is true for data encryption and session management.

Note: Lower numbers are a lower layer, while higher numbers are a higher layer.

From the Application Layer to the Transport Layer

The chart above shows that the transport layer sits directly below the Application Layer in the TCP/IP model. The high-level software developer's design and library choices impact the transport layer used for communication. However, they don't have full access to the details of that layer, such as TCP's ACKs.

In Python, for example, the socket module enables sending TCP and UDP messages directly. Immediately below is a client and server example using TCP:

import socket

def tcp_client(server_ip, server_port, message):
    # Create a TCP socket
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        # Connect to the server
        s.connect((server_ip, server_port))
        
        # Send data
        s.sendall(message.encode())

        # Receive response
        response = s.recv(1024)
        print(f"Received: {response.decode()}")

# Example usage
tcp_client("127.0.0.1", 12345, "Hello, TCP server!")
import socket

def tcp_server(host, port):
    # Create a TCP socket
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        # Bind the socket to address
        s.bind((host, port))
        s.listen()

        print(f"TCP server listening on {host}:{port}")

        # Accept connections
        conn, addr = s.accept()
        with conn:
            print(f"Connected by {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                print(f"Received message: {data.decode()}")
                conn.sendall(b"ACK")

# Example usage
tcp_server("0.0.0.0", 12345)

And one using UDP:

import socket

def udp_client(server_ip, server_port, message):
    # Create a UDP socket
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
        # Send data to server
        s.sendto(message.encode(), (server_ip, server_port))

        # Receive response
        response, _ = s.recvfrom(1024)
        print(f"Received: {response.decode()}")

# Example usage
udp_client("127.0.0.1", 12345, "Hello, UDP server!")
import socket

def udp_server(host, port):
    # Create a UDP socket
    with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
        # Bind the socket to address
        s.bind((host, port))
        print(f"UDP server up and listening on {host}:{port}")

        while True:
            # Receive message
            data, addr = s.recvfrom(1024)
            print(f"Received message: {data.decode()} from {addr}")

            # Send response
            s.sendto(b"ACK", addr)

# Example usage
udp_server("0.0.0.0", 12345)

Note: Above code provided by ChatGPT from OpenAI + minor adjustments.

Comparison

TCPUDP
ConnectionEstablishes connectionConnectionless
ReliabilityHigh (uses acknowledgements of receipt and error recovery)Low (no acknowledgements of receipt or error recovery)
SpeedSlower due to overhead of reliability mechanismsFaster due to lack of reliability overhead
Data OrderSequentialNo guaranteed order
BroadcastingNot supportedSupported
Use Case ExamplesWeb browsing, emailStreaming, gaming

A significant portion of the overhead in TCP comes from the connection establishment process. This is important because the responsibility of closing that connection is up to the higher-level (Application Layer) protocol (often HTTP). As such, HTTP/1.1 introduced keep-alive to use the same connection for multiple requests sequentially. Then, HTTP/2 took it a step further by introducing multiplexing, which allows multiple request/response cycles to traverse the connection concurrently.

The Future

HTTP3 (introduced in 2022) breaks with the tradition of using TCP and uses QUIC (Quick UDP Internet Connections) instead. QUIC's primary feature enhancements are reduced overhead in establishing a connection, and more granular handling of multiple requests in a multiplexed connection, preventing blocking during error recovery.



To be updated in the new year with a deeper dive.