SubnetLayer

TCP

Transmission Control Protocol

TCP turns the Internet's unreliable, unordered packet delivery into the reliable byte streams that the web, mail, and SSH are built on. It does that with a handful of ideas — numbered bytes, acknowledgements, windows, timers — and you can watch every one of them at work in the packets themselves. Each lesson below runs a real simulated capture: play it, pause it, decode any packet down to its bits, and export it to Wireshark.

Why does this protocol exist?
IP loses, reorders and duplicates packets and tells nobody. Almost every application needs the opposite. Solving that once, in the operating system, is better than solving it in every application.
Which problem does it solve?
Turn unreliable, unordered packet delivery into a reliable, ordered byte stream between two programs, without overwhelming either the receiver or the network.
Who participates?
Exactly two endpoints. One initiates (the client, by definition the sender of the first SYN); one was listening (the server). Both hold equal amounts of state.
Which layer uses it?
Transport layer. Carried in IP with protocol number 6.
What does it depend on?
IPv4 for delivery. It assumes nothing else, which is why it runs over any path.
What depends on it?
HTTP, TLS, BGP, SMTP, SSH — most of what people mean by 'the internet'. BGP's choice of TCP is why it needs no retransmission of its own.
What state does each participant maintain?
A great deal, on both sides: connection state (LISTEN, SYN-SENT, ESTABLISHED, FIN-WAIT…), the next sequence number to send, the highest byte acknowledged, the receive window, the congestion window, and several timers. This is what a 'connection' actually is.
Which fields matter?
  • seq Numbers the first byte of this segment within the stream. Not a packet counter — this is the most common misreading.
  • ack The next byte expected. It is cumulative: it acknowledges everything before it, not the segment that just arrived.
  • flags SYN and FIN establish and close and each consume one sequence number; RST aborts; ACK is set on everything after the first packet.
  • window How much the receiver can still take. Flow control, not congestion control — and scaled by a factor negotiated in the handshake.
  • options MSS, window scale, SACK permitted and timestamps are all negotiated in the SYN, and can only be negotiated there.
What does normal behaviour look like?
SYN, SYN-ACK, ACK, then data with acknowledgements flowing back, then FIN in each direction. Sequence numbers advance by the number of data bytes; the window opens and closes as the receiver reads.
What does failure look like?
SYN with no answer at all (a blackhole — filtered). SYN answered with RST (nothing listening). Repeated identical segments (loss and retransmission). A window that reaches zero and stays there (the receiver has stopped reading).
How can I prove the diagnosis from packets?
Follow the sequence and acknowledgement numbers. A retransmission is a segment with a sequence number already sent. A stall is an acknowledgement that stops advancing. A zero window is stated in the header directly. This app's seq/ack ledger is built for exactly this reading.
How does it interact with the rest of the stack?
TCP sits on IP and carries TLS and HTTP. It reacts to ICMP: fragmentation-needed changes its segment size, port-unreachable can abort it. It is where reliability lives, and everything above it is written assuming that reliability already exists.
Never read a packet capture before? Start with Networking Foundations

Layers, addresses, masks, gateways, ports and byte order — the ideas every module here assumes, taught without a single capture.

🎓 New to TCP? Start with the foundations

The ideas every lesson builds on — what TCP promises (and what it doesn't), how a segment differs from a packet, what identifies a connection, why a connection is really two byte streams, and the difference between the two windows. No packet captures on that page: just the concepts, with diagrams, at whichever depth suits you.

Guided course — 15 lessons

Read in order. Every lesson pauses the capture on the packets it is talking about, and every one reads at three levels — so the time below is an estimate from the number of steps, not a measurement of anybody.

  1. 1TCP-01TCP Header AnatomyEvery field of the header, on a real packet15 min · 10 steps · 3 questions · guidedNot started
  2. 2TCP-02The Three-Way HandshakeSYN → SYN-ACK → ACK: how every connection begins15 min · 10 steps · 4 questions · guided · after tcp-header-anatomyNot started
  3. 3TCP-03Sequence & Acknowledgement NumbersHow TCP counts every byte — and never loses track15 min · 9 steps · 3 questions · guided · after three-way-handshakeNot started
  4. 4TCP-04Basic Data TransferFrom an application's write() to segments on the wire15 min · 8 steps · 3 questions · guided · after three-way-handshake, sequence-and-ack-numbersNot started
  5. 5TCP-05The TCP FlagsEight bits that steer every connection15 min · 9 steps · 4 questions · guided · after three-way-handshakeNot started
  6. 6TCP-06Sliding Window & Flow ControlHow a receiver throttles a sender — down to a dead stop20 min · 11 steps · 4 questions · guided · after sequence-and-ack-numbersNot started
  7. 7TCP-07Retransmission After Packet LossTimers, duplicate ACKs, and how TCP refuses to lose data20 min · 11 steps · 4 questions · guided · diagnosis lab · after sequence-and-ack-numbers, basic-data-transferNot started
  8. 8TCP-08Connection TerminationFIN, ACK, FIN, ACK — and the mysterious TIME-WAIT15 min · 10 steps · 4 questions · guided · after three-way-handshake, basic-data-transferNot started
  9. 9TCP-09TCP ResetRST: connection refused, connection destroyed10 min · 8 steps · 4 questions · guided · diagnosis lab · after three-way-handshake, connection-terminationNot started
  10. 10TCP-10Troubleshooting Lab: The Site That Never LoadsRead the evidence. Name the culprit.15 min · 9 steps · 3 questions · guided · diagnosis lab · after three-way-handshake, retransmission-packet-loss, tcp-resetNot started
  11. 11TCP-11Congestion ControlSlow start, fast retransmit, and why the whole Internet doesn't melt20 min · 12 steps · 4 questions · guided · diagnosis lab · after sliding-window-flow-control, retransmission-packet-lossNot started
  12. 12TCP-12The Silly Window SyndromeRFC 813 · how a correct connection talks itself into tiny, wasteful packets15 min · 10 steps · 4 questions · guided · after sliding-window-flow-controlNot started
  13. 13TCP-13The Nagle AlgorithmRFC 896 · one sentence that tamed the tinygram flood15 min · 8 steps · 3 questions · guided · after basic-data-transferNot started
  14. 14TCP-14Zero-Window ProbesRFC 1122 §4.2.2.17 · how a stalled connection stays alive15 min · 9 steps · 3 questions · guided · after sliding-window-flow-controlNot started
  15. 15TCP-15Congestion CollapseRFC 896 · the prophecy: a network drowning in its own retries15 min · 9 steps · 4 questions · guided · diagnosis lab · after retransmission-packet-loss, congestion-controlNot started

Troubleshooting labs — 5

A symptom, a capture, and no answer given. Each one is a lesson from the course above, listed again here because the diagnosis is worth coming back for.

TCP — end of module →

Sequence arithmetic, the state each end is in, and telling a refusal apart from a silence. Four questions, and none of them can be answered by remembering a trace.

Build-a-Packet — craft your own segment

Construct a TCP packet field by field

Choose flags, ports, sequence numbers, options, and payload. The app encodes your packet to real bytes, validates it against TCP's rules, and explains every mistake — then lets you export it as a Wireshark-compatible capture.

Packet explorer — inspect any scenario freely

Three-way handshake

A browser opens http://shop.example.test — connection setup only.

HTTP request and response

After the handshake, the browser sends a GET and the server answers.

A complete TCP conversation

Handshake, HTTP exchange, and a polite four-way close — every common flag in one trace.

Flow control and the zero window

A client uploads 6000 bytes to a slow server whose application stops reading — the window closes to zero, then reopens.

Packet loss and retransmission

The first data segment is lost in transit. A later segment triggers a duplicate ACK, the retransmission timer fires, and TCP recovers.

Four-way connection termination

Both sides close politely: FIN, ACK, FIN, ACK — then TIME-WAIT.

Connecting to a closed port

Nothing is listening on port 80 — the SYN is answered with an immediate RST.

Reset in the middle of a connection

The server application crashes mid-conversation and aborts with an RST.

Slow start, loss, and fast recovery

A client uploads a 21.9 KB file. Watch cwnd double each round trip, one segment get lost, three duplicate ACKs trigger a fast retransmit, and the window halve.

RFC 813 · Healthy window usage

A 6 KB upload to a well-behaved receiver: full-sized segments, prompt reads, steady cumulative ACKs — window management as intended.

RFC 813 · Receiver silly window syndrome

The server app sips 200 bytes at a time and the stack advertises every tiny opening (no SWS avoidance) — watch the connection degenerate into 200-byte crumbs.

RFC 813 · The cure — SWS avoidance on both sides

Identical sipping application, but the stack follows RFC 9293: window updates held until worth advertising, no crumb segments sent. Same app, healthy wire.

RFC 896 · The small-packet problem

Eight keystrokes typed into a remote session with Nagle disabled: one 41-byte-overhead packet per byte of typing.

RFC 896 · The Nagle algorithm

The same eight keystrokes with Nagle enabled: the first byte goes immediately, the rest coalesce behind the outstanding ACK — self-clocked batching.

RFC 879 · Asymmetric MSS announcements

Client announces MSS 1460, the constrained server announces 536. Each direction obeys the OTHER side's number — watch 1200 bytes travel as 536+536+128 one way and as a single segment the other.

RFC 1122 · Delayed acknowledgements

A 4-segment transfer with RFC 1122 §4.2.3.2 delayed ACKs: one ACK per two full segments, and a lone trailing segment ACKed only when the 200 ms timer expires.

RFC 879 · The missing MSS option

The client's SYN carries NO MSS option — so the server must assume the ancient default of 536 bytes and chops its 1200-byte response into 536-byte pieces, even though the client could take 1460.

RFC 879 · MSS clamped by a middlebox

The client announces MSS 1460, but a middlebox on the path rewrites the SYN's option to 536 in transit. The server obediently sends small segments — and the client never knows why. Inspect the SYN: the wire disagrees with the sender.

RFC 896 · Congestion collapse in miniature

A slow link (60 B/ms), a 4-packet router queue, and a sender whose RTO (80 ms) is shorter than the queue-inflated RTT: premature retransmissions flood the queue with duplicates, drops multiply, and goodput falls while total traffic rises.

RFC 896 · Same link, patient timer

The identical slow, shallow-queued link — but with a conservative 1-second RTO. The burst tail still overflows the queue, yet every retry now answers a REAL loss: no spurious copies, no duplicates competing with live data.

RFC 1122 · Zero-window probes (persist timer)

The receiver's window closes and stays closed for three seconds. A compliant sender probes it — 500 ms, then 1 s, then 2 s — so the reopening can never be lost, then finishes the transfer.

Compliance case · No exponential backoff

Every data segment is being lost, and this sender retries at a FIXED interval instead of doubling it. Read the timer events: is this host compliant?

Compliance case · The receiver that never acknowledges

Data arrives intact — and vanishes. No ACK ever covers it. Watch the sender retry with growing patience and finally give up. Which host broke the rules, and which packets prove it?

Compliance case · Sender ignores the zero window

The receiver advertises window 0 — and this sender keeps transmitting anyway. Watch the receiver discard the overrun segments and re-ACK the same edge, over and over.

RFC 7323 · Long fat pipe WITHOUT window scaling

A 200 ms satellite-class path and 256 KB of buffer on both sides — but no window scaling, so the 16-bit window field caps everything at 65,535 bytes in flight. Watch the sender idle between window-fulls.

RFC 7323 · The same path WITH window scaling

Identical path and buffers, but both SYNs offer Window Scale (shift 3). The window field now means ×8, the full 256 KB is usable, and the same file finishes in a fraction of the time.

RFC 7323 · Different scale factors per direction

The client offers shift 2 (×4), the server shift 7 (×128). Both are honoured — each side scales what IT receives. Inspect the two SYNs and the window fields that follow.

RFC 7323 · One side doesn't offer scaling

The client offers Window Scale; the (older) server's SYN-ACK carries none. Per RFC 7323 §2.2 the offer is void for BOTH directions — watch the connection fall back to raw 16-bit windows.

RFC 7323 · Timestamps measuring the round trip

Every segment carries TSval/TSecr. Each returning ACK echoes the timestamp of the data it acknowledges, giving the sender an exact RTT sample — the raw material for the retransmission timer.

RFC 2018 · Two holes, cumulative ACK only

Eight segments; two non-adjacent ones vanish. The receiver can only repeat one number — 'I still need byte X' — so the sender resends far more than was lost.

RFC 2018 · The same two holes, with SACK

Identical losses, but SACK-Permitted was negotiated: the receiver now reports exactly which ranges arrived, and the sender retransmits only the two missing segments.

RFC 6298 · Measuring a steady path

Four request/response exchanges over a rock-steady 40 ms path. Watch SRTT lock onto 40 ms while RTTVAR decays toward zero — and the RTO sit stubbornly at its 1-second floor.

RFC 6298 · A sudden latency spike

The same steady path, but one response is delayed by 400 ms. Watch a single outlier widen RTTVAR sharply — the estimator buying safety margin exactly when the path proves unpredictable.

RFC 6298 · Backoff and Karn's rule

A segment is lost, the timer fires and doubles, and the retransmission is finally acknowledged — but that ACK is AMBIGUOUS (which copy did it answer?), so Karn's rule throws the sample away instead of poisoning SRTT.

RFC 2988 · The old 3-second initial RTO

Identical loss, but the pre-2011 rules: with no measurement yet, the first timer is 3 seconds instead of 1. Compare how long the connection sits blind before it acts.

RFC 6298 · The current 1-second initial RTO

The same loss under today's rules: the first timer is 1 second, so recovery starts two seconds sooner. This single constant is the headline change from RFC 2988.

RFC 5681 · Receiver window smaller than cwnd

cwnd has grown large but the receiver only advertises 4 KB. The sender may use min(cwnd, rwnd) — so flow control, not congestion control, is the brake here.

RFC 5681 §4.1 · Restart after an idle period

A burst grows cwnd nicely, then the application goes quiet for eight seconds. When it speaks again the ACK clock is long gone — so cwnd restarts at the initial window rather than trusting stale evidence.

Mystery: the connection just hangs

A user reports that shop.example.test never loads. The capture shows what their machine sent — work out what is wrong.

Comparison labs — 8

The same scenario run twice, side by side on one clock, with and without the behaviour a standard introduced — so the difference it made is visible rather than described.

Reference material — the RFCs behind these lessons

Window scaling, timestamps, SACK, RTO estimation, Nagle and silly-window avoidance each have a module of their own — the problem that was found, the fix that was standardised, and a capture of both. Lessons 12 to 15 are the guided walkthroughs; the library has the rest.

RFC Library — nine RFCs, with the traffic that motivated each

Including compare mode, which runs two versions of the same scenario side by side so the difference a standard made is visible rather than described.

Continue through the protocol stack

TCP does not run on its own. Everything below carries it, is carried by it, or decides where its packets go — each with its own module, lessons, and captures.