TCP (Transmission Control Protocol) is a connection-oriented, reliable, byte-stream protocol that operates at the Transport Layer (Layer 4) of the OSI model.
| Aspect | TCP | UDP |
|---|---|---|
| Connection | Connection-oriented | Connectionless |
| Reliability | Guaranteed delivery | Best effort (no guarantees) |
| Ordering | In-order delivery | No ordering |
| Speed | Slower (overhead) | Faster (minimal overhead) |
| Use cases | HTTP, FTP, email, SSH | DNS, streaming, gaming, VoIP |
Purpose: Synchronize sequence numbers, establish connection parameters (window size, MSS)
Note: Client enters TIME_WAIT state (2xMSL) to handle delayed packets before fully closing.
How it works:
Client sends: SEQ=1000, Data="Hello" (5 bytes)
Server ACKs: ACK=1005 (expecting byte 1005 next)
Client sends: SEQ=1005, Data="World" (5 bytes)
Server ACKs: ACK=1010
# If packet lost:
Client sends: SEQ=1010, Data="!!!" (3 bytes)
[packet lost, server doesn't receive it]
Client sends: SEQ=1013, Data="Next" (4 bytes)
Server ACKs: ACK=1010 (still waiting for byte 1010-1012)
TCP uses adaptive timeout based on Round-Trip Time (RTT):
Don't use RTT samples from retransmitted segments (ambiguous - which transmission was ACKed?).
Don't wait for timeout if you get 3 duplicate ACKs:
Client sends: SEQ=1000, SEQ=1500, SEQ=2000, SEQ=2500
Server receives: 1000, 1500 (lost), 2000, 2500
Server sends: ACK=1500, ACK=1500, ACK=1500, ACK=1500
(duplicate ACKs because still waiting for 1500)
Client receives 3 duplicate ACKs - immediately retransmits SEQ=1500
(Don't wait for timeout!)
Purpose: Prevent sender from overwhelming receiver's buffer.
How it works:
rwnd bytes without waiting for ACKUsable Window: Initially 2000 bytes (3000-4999), after ACK: 3000 bytes (3000-5999)
# Initial state
Receiver buffer: 10KB free - advertises rwnd=10240
Sender sends: 5KB of data
# Receiver processes 2KB, has 7KB in buffer
Receiver ACKs with: rwnd=3072 (10KB - 7KB)
Sender can now send up to 3072 bytes
# Receiver processes all buffered data
Receiver ACKs with: rwnd=10240 (buffer empty)
Sender can send full window again
Flow control (sliding window) handles receiver capacity. Congestion control handles network capacity - preventing routers from being overwhelmed.
Purpose: Quickly find available bandwidth without causing congestion.
How it works:
RTT 1: cwnd = 1 MSS - send 1 packet
Receive 1 ACK - cwnd = 2 MSS
RTT 2: cwnd = 2 MSS - send 2 packets
Receive 2 ACKs - cwnd = 4 MSS
RTT 3: cwnd = 4 MSS - send 4 packets
Receive 4 ACKs - cwnd = 8 MSS
RTT 4: cwnd = 8 MSS - send 8 packets
Receive 8 ACKs - cwnd = 16 MSS
# Exponential growth: 1 - 2 - 4 - 8 - 16 - 32 - 64 ...
Purpose: Increase bandwidth usage cautiously after slow start.
How it works:
Assume ssthresh = 16 MSS
RTT 1: cwnd = 16 MSS - cwnd = 17 MSS (increase by 1)
RTT 2: cwnd = 17 MSS - cwnd = 18 MSS
RTT 3: cwnd = 18 MSS - cwnd = 19 MSS
RTT 4: cwnd = 19 MSS - cwnd = 20 MSS
# Linear growth: 16 - 17 - 18 - 19 - 20 ...
Option A: Timeout (severe congestion)
Option B: 3 Duplicate ACKs (mild congestion)
When timeout occurs, TCP halves the congestion window (multiplicative decrease) and may double the RTO for retransmissions. This is the exponential backoff mechanism that prevents overwhelming a congested network.
# Scenario 1: Timeout
cwnd = 32 MSS
[Timeout occurs]
ssthresh = 32 / 2 = 16 MSS
cwnd = 1 MSS
- Restart slow start, grow to 16, then congestion avoidance
# Scenario 2: 3 Duplicate ACKs
cwnd = 32 MSS
[3 duplicate ACKs received]
ssthresh = 32 / 2 = 16 MSS
cwnd = 16 MSS
- Fast recovery, enter congestion avoidance immediately
The core principle of TCP congestion control:
Result: TCP "probes" for available bandwidth, backing off when congestion detected.
Pattern: Slow Start (exponential) - Congestion Avoidance (linear) - Loss (decrease) - Repeat
| Algorithm | Loss Detection | Response | Notes |
|---|---|---|---|
| Tahoe | Timeout or 3 dup ACKs | cwnd = 1, restart slow start | Original, very conservative |
| Reno | Timeout: cwnd = 1 3 dup ACKs: Fast Recovery |
Fast Retransmit + Fast Recovery | Most common classic algorithm |
| NewReno | Like Reno, better multi-loss handling | Improved fast recovery | Handles multiple losses in one window |
| CUBIC | Like Reno | Cubic function for cwnd growth | Default in Linux, better for high-bandwidth |
| BBR | Doesn't rely on loss | Model-based, optimizes for throughput + latency | Google's algorithm, used in YouTube |
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Source Port | Destination Port |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Acknowledgment Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data | |C|E|U|A|P|R|S|F| |
| Offset| Rsrvd |W|C|R|C|S|S|Y|I| Window |
| | |R|E|G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Checksum | Urgent Pointer |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Options | Padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
TCP elegantly solves multiple hard problems:
Why TCP is still dominant after 40+ years: Its fundamental design principles (end-to-end reliability, congestion control, flow control) remain sound. Modern variants (CUBIC, BBR) improve performance while keeping the core mechanisms.