Skip to main content
How systems communicate — TCP/IP, HTTP, DNS, load balancing, and security.

Networking

How systems communicate — TCP/IP, HTTP, DNS, load balancing, and security.

TCP Protocol & Flow Visualizer

3-Way Handshake + Teardown

Step 0 / 0
Speed 200ms
Step 0 / 0
Phase init
Window (cwnd / rwnd) —
Dup ACKs / Loss 0
Status Ready
Client CLOSED
Server LISTEN
Client → Server
Server → Client
Active Packet
Dropped / Loss
Step Explanation

Press Play to run the TCP sequence simulation.

—
Pseudocode
 

TCP & UDP Deep Dive

Elementary (2/5) ~2–3 hours TCP Handshake Flow Control Congestion Control UDP Datagrams Ports & Sockets Prereqs: Network Models (OSI, TCP/IP)
Quick Reference

handshake

No registry entry found for algorithm id "handshake". If this is a curriculum-only studio, the complexity and quick-reference panel is intentionally omitted.

One Network, Two Philosophies

The transport layer delivers data between two processes (identified by ports) on top of the best-effort network layer. IP alone does not guarantee delivery, ordering, or integrity — so TCP exists to add those guarantees, and UDP exists to skip them for speed. Which one you choose is a semantic decision: “I need a reliable byte stream” → TCP; “I need low latency / real-time delivery” → UDP.

Ports and the Four-Tuple

A port (0–65535) identifies a process on a host. A TCP or UDP connection is uniquely identified by the four-tuple: (source IP, source port, dest IP, dest port). This is why thousands of connections can share one server IP — each has a distinct source port. Well-known ports you must know: HTTP 80, HTTPS 443, DNS 53, SSH 22, MySQL 3306, Postgres 5432, Redis 6379. A socket is the OS API object at the endpoint of one such four-tuple.

The TCP Three-Way Handshake

TCP is connection-oriented: before data flows, the endpoints agree on sequence numbers and parameters:

Client                     Server
  │   SYN, seq=1000          │
  ├──────────────────────────▶  (Server stores client seq)
  │   SYN-ACK, seq=5000, ack=1001 │
  ◀──────────────────────────┤
  │   ACK, seq=1001, ack=5001 │
  ├──────────────────────────▶
  │   [ data flows both ways ]

The handshake allocates state on both ends (the SYN-ACK proves the server is reachable and willing). This is also the heart of the classic SYN flood denial-of-service: the server holds half-open connections waiting for the final ACK that never comes.

Teardown uses four packets (FIN → FIN-ACK → FIN → FIN-ACK) — and since teardown is cooperative, a crashed peer leaves “TIME_WAIT” and “CLOSE_WAIT” states that netstat/ss show. A server full of CLOSE_WAIT sockets is a bug in your application (it never closed its end); TIME_WAIT buildup is usually just socket reuse policy.

Reliability: Sequence Numbers and ACKs

Once connected, TCP treats data as a byte stream:

  • Every byte has a sequence number (seq).
  • The receiver ACKs the next byte it expects (ack = last received + 1).
  • The sender retransmits anything not ACKed within a timeout (estimated from round-trip time).

This gives: no loss, no duplication, correct ordering, and an end-to-end checksum. The cost is latency under loss — if a packet drops, the stream stalls until the ACK gap is repaired (in-order delivery = head-of-line blocking). Real-time apps (video calls, games) can’t afford that, which is why they use UDP and accept the loss.

Flow Control vs Congestion Control

Two windows control how much TCP sends, and they answer different questions:

  • Flow control — “how much can the receiver take?” The receiver advertises a receive window; the sender never exceeds it (sliding window). Prevents buffer overflow at the destination.
  • Congestion control — “how much can the network take?” The sender maintains a congestion window (cwnd) that it probes and shrinks. Prevents overloading routers.

Congestion control is where the magic lives. Modern TCP uses AIMD — Additive Increase, Multiplicative Decrease:

  1. Slow start — double cwnd each round trip (exponential) until a threshold or loss.
  2. Congestion avoidance — add ~1 MSS per RTT (linear growth).
  3. On loss (timeout or triple duplicate ACK) — cut cwnd in half (or reset).

The result is TCP converges on “as much bandwidth as the network safely allows,” oscillating gently around the bottleneck. This is why bulk transfers slow down on lossy links: TCP reads every drop as congestion and backs off — the deep reason “high packet loss = low throughput” even when bandwidth is plenty.

UDP: Best-Effort Datagrams

UDP sends self-contained datagrams with a checksum and ports — no handshake, no state, no retransmission, no ordering:

  • Pros: minimal header (8 bytes), zero connection setup, no head-of-line blocking, one-to-many via broadcast/multicast.
  • Cons: no delivery guarantee, no ordering, no congestion control — apps must add what they need.
Uses UDPUses TCP
DNS (single question/answer)HTTP/HTTPS, email, file transfer
Video/voice (real-time, tolerates loss)SSH, databases, any reliable stream
QUIC (HTTP/3)Anything needing guaranteed delivery
Game/sensor telemetry

The eternal systems rule: UDP is not “TCP without guarantees” — it’s a different contract. If your application needs reliability on UDP, you rebuild a mini-TCP (sequence numbers, ACKs, retransmission) — which is exactly what QUIC did, with modern congestion control on top of UDP to dodge head-of-line blocking.

TCP in Practice: the Hidden Draggers

Four implementation details explain a mountain of real-world “why is this slow?” mysteries:

  • Nagle’s algorithm — batches small writes to reduce tiny segments; interacts badly with interactive protocols unless you disable it (TCP_NODELAY) for low-latency chat.
  • Delayed ACK — the receiver waits ~40 ms before ACKing to piggyback on replies; pairs badly with Nagle (the “Nagle + delayed ACK deadlock”).
  • Head-of-line blocking — one lost segment stalls every later one, which is why HTTP/3 and QUIC moved to UDP.
  • Buffer bloat — long queueing at routers inflates latency; TCP’s only signal for congestion is loss, so it fills buffers (the argument for BBR/AQM schemes).

Practice Trajectory

  1. ss -tn (or netstat -tn) and identify established connections by their four-tuple; pick one and say which process owns each port.
  2. tcpdump -n -c 20 host google.com while curling google.com — spot the SYN/SYN-ACK/ACK handshake and the final FIN sequence.
  3. curl -w '%{time_connect} %{time_starttransfer}\n' twice — once over TCP/HTTP, and reason about where the handshake and ACK latency go.
  4. Simulate loss with tc netem loss 5% on a loopback veth and measure throughput drop on a bulk TCP transfer — explain via congestion control.
  5. Explain the four-tuple to someone else from memory, then list three apps that should use UDP and why.

When It’s the Right Tool

SituationTakeaway
Any reliable client-server dataTCP
Real-time media, games, telemetryUDP
Explaining “slow over lossy links”Congestion control, not bandwidth
Debugging connection statesTIME_WAIT/CLOSE_WAIT/half-open are TCP state-machine artifacts
Modern HTTP/3QUIC = TCP’s guarantees re-built on UDP to kill head-of-line blocking