TCP, IP, and UDP: Understanding Internet Transport Protocols

Compare TCP vs UDP, learn the three-way handshake, flow control, congestion control, and when to use each protocol for developers.

published: reading time: 11 min read

TCP, IP, and UDP: Understanding Internet Transport Protocols

The internet runs on protocols. TCP and UDP are the two main transport protocols that sit on top of IP. Understanding what they do and when to use each one matters for system design, networking, and debugging.

The HTTP/HTTPS protocol post covers application-layer protocols. This post goes deeper into the transport layer.


The Protocol Stack

Networking uses a layered model. Each layer handles specific responsibilities:

graph TB
    A[Application Layer<br/>HTTP, DNS, SMTP] --> B[Transport Layer<br/>TCP, UDP]
    B --> C[Internet Layer<br/>IP]
    C --> D[Link Layer<br/>Ethernet, WiFi]

IP handles addressing and routing. TCP and UDP sit on top of IP, adding their own features. You rarely choose between TCP and UDP directly; you choose an application protocol that uses one or the other.


TCP: Transmission Control Protocol

TCP is connection-oriented. Before sending data, the client and server establish a connection. This connection stays open throughout the conversation and closes when done.

The Three-Way Handshake

TCP uses a three-way handshake to establish connections:

sequenceDiagram
    participant Client
    participant Server
    Client->>Server: SYN (seq=x)
    Server->>Client: SYN-ACK (seq=y, ack=x+1)
    Client->>Server: ACK (ack=y+1)
    Note over Client,Server: Connection established!
  1. Client sends SYN with a sequence number
  2. Server responds with SYN-ACK, acknowledging the client’s sequence number and sending its own sequence number
  3. Client sends ACK, acknowledging the server’s sequence number

This takes a full round trip before any data can be sent. HTTPS adds TLS on top, requiring more round trips.

Reliable Data Transfer

TCP guarantees that data arrives intact and in order. It does this through:

  • Acknowledgments (ACKs) - Receiver confirms receipt of data
  • Sequence numbers - Data is numbered so the receiver can reorder out-of-order packets
  • Retransmission - If data is not acknowledged, it is retransmitted
// TCP guarantees (simplified)
const sender = {
  sequence: 0,
  send(data) {
    const packet = { data, sequence: this.sequence };
    this.sequence += data.length;
    return packet;
  },
};

const receiver = {
  expectedSequence: 0,
  receive(packet) {
    if (packet.sequence === this.expectedSequence) {
      this.expectedSequence += packet.data.length;
      return { ack: packet.sequence + packet.data.length };
    }
    // Out of order - request retransmission
    return { ack: this.expectedSequence };
  },
};

Flow Control

TCP prevents the sender from overwhelming the receiver. The receiver advertises a window size indicating how much buffer space it has. The sender cannot send more than this window without receiving acknowledgments.

// Flow control window
const receiver = {
  bufferSize: 65535,
  usedBuffer: 0,
  windowSize() {
    return this.bufferSize - this.usedBuffer;
  },
};

Congestion Control

TCP also prevents overwhelming the network. It uses algorithms like slow start, congestion avoidance, and fast retransmit to dynamically adjust sending rate.

graph LR
    A[Slow Start] --> B[Congestion<br/>Avoidance]
    A -->|"packet loss"| C[Reduce Rate]
    B -->|"packet loss"| C
    C --> A

Slow start begins with a small window and exponentially increases it until packets are lost. This probing helps TCP find the available bandwidth without causing congestion.


UDP: User Datagram Protocol

UDP is simpler than TCP. It is connectionless and does not provide reliability, ordering, or flow control. Data is sent as datagrams, and the sender does not wait for acknowledgment.

UDP Characteristics

  • No connection establishment (zero latency)
  • No ordering or sequencing
  • No retransmission of lost packets
  • Small header overhead (8 bytes vs TCP’s 20+ bytes)
// UDP is simple
const sender = {
  send(data, address) {
    const datagram = { data, destination: address };
    // Send and forget - no acknowledgment
    return datagram;
  },
};

const receiver = {
  receive(datagram) {
    // Handle datagram - might be duplicate, might be missing
    return datagram.data;
  },
};

UDP Header

UDP has a minimal header:

+----------------+----------------+----------------+----------------+
| Source Port    | Dest Port     | Length        | Checksum       |
+----------------+----------------+----------------+----------------+

Four 16-bit fields. Source port is optional (set to 0 if not used). Length includes header and data. Checksum for error detection.


TCP vs UDP Comparison

FeatureTCPUDP
ConnectionConnection-orientedConnectionless
ReliabilityGuaranteed deliveryBest effort
OrderingIn-order deliveryNo ordering
SpeedSlower (handshake, ACKs)Faster (no overhead)
Header size20+ bytes8 bytes
Flow controlYesNo
Congestion controlYesNo

When to Use TCP

TCP is the right choice when:

  • You need all data to arrive intact
  • Order matters (files, messages, documents)
  • You can tolerate some latency
  • You are building HTTP servers, email, file transfer

Most web traffic uses TCP. The reliability guarantees mean you do not have to handle missing or duplicate data yourself.

When to Use UDP

UDP works well when:

  • Speed matters more than reliability
  • Real-time applications (voice, video, gaming)
  • You want minimal overhead
  • Application-level error handling is sufficient
  • Multicast or broadcast is needed
// Good UDP use cases
const videoStream = {
  protocol: "UDP",
  // Missing frames are less noticeable than delay
  // Accept some packet loss for real-time playback
};

const voiceCall = {
  protocol: "UDP",
  // Prefer hearing the other person with small gaps
  // Over hearing them perfectly but delayed
};

const dnsQuery = {
  protocol: "UDP",
  // Fast lookup matters more than perfect reliability
  // DNS servers retry if no response
};

Port Numbers

Both TCP and UDP use port numbers to multiplex connections. Ports range from 0 to 65535. Well-known ports (0-1023) are reserved for common services:

PortServiceProtocol
80HTTPTCP
443HTTPSTCP
53DNSUDP (also TCP)
22SSHTCP
25SMTPTCP

Your application can use any port above 1024. Node.js http.createServer() defaults to port 3000, for example.


Common Misconceptions

”UDP is always faster”

UDP avoids TCP overhead, but speed depends on the network. On a reliable local network, UDP can transmit faster. On the public internet with packet loss, TCP’s congestion control actually helps it perform well.

”TCP is for files, UDP is for video”

Many video streaming platforms use TCP. The overhead is acceptable, and TCP’s reliability ensures frames are not dropped. Real-time video calls often use UDP for lower latency, but they build their own reliability layer for important data.

”You always choose between TCP and UDP”

Usually your application protocol decides this for you. HTTP uses TCP. DNS usually uses UDP but switches to TCP for large responses. WebRTC uses UDP for media but TCP for signaling.


Connecting It All Together

The layers build on each other:

graph TB
    A[Your Application] --> B[HTTP over TCP]
    B --> C[TCP over IP]
    C --> D[IP over Ethernet]
    D --> E[Physical Network]

Each layer encapsulates the one below it. Your HTTP request becomes a TCP segment, then an IP packet, then an Ethernet frame.


Production Failure Scenarios

FailureImpactMitigation
TCP connection timeoutRequests hang; poor user experienceSet appropriate connection timeouts; implement retry logic
UDP packet lossMissing data; application-level failuresImplement application-level acknowledgment and retransmission
Port exhaustionCannot establish new connections; service unavailableMonitor connection counts; implement connection pooling; increase port range
SYN flood attackServer overwhelmed with half-open connectionsUse SYN cookies; implement rate limiting; use DDoS protection
NAT timeoutLong-lived connections break; clients appear disconnectedSend keepalive packets; use connection-oriented protocols when possible
MTU mismatchPackets dropped; connectivity issuesUse Path MTU Discovery; set conservative MTU values
TCP congestion collapseNetwork throughput drops dramaticallyUse proper congestion control algorithms; implement traffic shaping
UDP amplification attackYour servers used to attack othersValidate source addresses; restrict UDP responses; implement rate limiting

Observability Checklist

Metrics

  • TCP connection rate (new connections per second)
  • Active TCP connections (concurrent connections)
  • TCP connection failures (connection refused, timeout)
  • Segment retransmission rate
  • TCP buffer utilization (bytes in send/receive buffers)
  • UDP packet rate (packets sent/received per second)
  • UDP error rate (checksum failures, buffer overflows)
  • Round-trip time (RTT) for TCP connections
  • Throughput (bytes sent/received per second)

Logs

  • Connection failures with source IP and port
  • TCP reset packets (RST) received
  • UDP packet checksum failures
  • Connection timeouts
  • Port exhaustion warnings
  • Network interface errors

Alerts

  • Connection failure rate exceeds 5%
  • Retransmission rate exceeds 10%
  • Active connections approach limits
  • UDP error rate increases
  • TCP RST rate spikes (potential attack)
  • Network latency anomalies

Security Checklist

  • Use TLS over TCP when encryption is needed (not raw TCP)
  • Implement connection timeouts to prevent resource exhaustion
  • Monitor for SYN flood attacks; enable SYN cookies
  • Use firewall rules to restrict exposed ports
  • Implement rate limiting on TCP/UDP services
  • Validate UDP source addresses to prevent spoofing
  • Use IPsec for network-level encryption when needed
  • Monitor for unusual traffic patterns indicating attacks
  • Implement connection tracking for stateful firewall rules
  • Restrict broadcast and multicast traffic where not needed

Common Pitfalls / Anti-Patterns

Assuming UDP is Always Faster

UDP avoids TCP overhead but does not guarantee delivery or ordering.

// Problem: UDP with no reliability
const socket = dgram.createSocket("udp4");
socket.send(data, port, host, (err) => {
  // No confirmation data arrived - you simply do not know
});

// Better: Implement acknowledgment
socket.send(data, port, host);
socket.on("message", (msg) => {
  if (msg.toString() === "ACK") {
    // Confirmed delivery
  }
});

Ignoring TCP Connection Limits

Each TCP connection consumes file descriptors and memory.

# Check current connection limits
cat /proc/sys/net/core/somaxconn        # Max pending connections
cat /proc/sys/fs/file-max               # System-wide file descriptors

# Monitor active connections
ss -s

Not Handling Connection Termination Properly

Abruptly closing connections can cause data loss.

// Graceful close - ensure data is sent
socket.end(); // Send FIN after remaining data is sent
socket.on("close", () => {
  // Connection fully closed
});

Building Custom Reliability on UDP When TCP Would Work

If you need reliable, ordered delivery, just use TCP.

// Problem: Building reliability on UDP
socket.on("message", (data) => {
  // Must implement sequence numbers, acknowledgments, retransmission
  // This is essentially reimplementing TCP
});

// Better: Just use TCP
const server = net.createServer((socket) => {
  // Reliability built in
});

Quick Recap

Key Bullets

  • TCP provides reliable, ordered, connection-oriented delivery with flow and congestion control
  • UDP provides fast, unreliable, connectionless delivery without overhead
  • TCP three-way handshake establishes connections; UDP sends immediately
  • TCP uses acknowledgments, sequence numbers, and retransmission for reliability
  • UDP header is 8 bytes; TCP header is 20+ bytes minimum
  • Choose TCP when correctness matters; choose UDP when speed and low latency matter more
  • Common TCP ports: 80 (HTTP), 443 (HTTPS), 22 (SSH), 25 (SMTP), 53 (DNS)
  • DNS uses UDP port 53 for queries, TCP for zone transfers and large responses

Copy/Paste Checklist

# Check TCP connection states
ss -tunapl | grep -E "(State|Recv-Q|Send-Q)"

# Monitor TCP metrics
cat /proc/net/tcp
cat /proc/net/tcp6

# Check UDP statistics
cat /proc/net/udp
cat /proc/net/udp6

# Test TCP connection with netcat
nc -zv host.example.com 443

# Test UDP connectivity (limited)
nc -zvu host.example.com 53

# Check for open ports
ss -tunapl | grep LISTEN

# View TCP window sizes
cat /proc/sys/net/ipv4/tcp_rmem
cat /proc/sys/net/ipv4/tcp_wmem

# Test MTU
ping -M do -s 1472 example.com

Conclusion

TCP and UDP serve different needs. TCP provides reliability, ordering, and flow control at the cost of latency. UDP provides speed and simplicity at the cost of reliability guarantees.

Choose TCP when correctness matters more than speed. Choose UDP when speed matters more than perfect reliability, or when you want to build your own reliability layer on top.

For application-layer protocols, see the HTTP/HTTPS post. For DNS specifically, the DNS & Domain Management post covers name resolution in detail.

Category

Related Posts

HTTP and HTTPS Protocol: A Complete Guide to Web Communication

Deep dive into HTTP methods, status codes, headers, keep-alive, and protocol evolution. Understand HTTP/1.1, HTTP/2, and HTTP/3 differences.

#networking #http #https

Cloud Security: IAM, Network Isolation, and Encryption

Implement defense-in-depth security for cloud infrastructure—identity and access management, network isolation, encryption, and security monitoring.

#cloud #security #iam

Docker Networking: From Bridge to Overlay

Master Docker's networking models—bridge, host, overlay, and macvlan—for connecting containers across hosts and distributed applications.

#docker #networking #containers