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.
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 foundationsThe 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.
- 1TCP-01TCP Header AnatomyEvery field of the header, on a real packet≈15 min · 10 steps · 3 questions · guidedNot started
- 2TCP-02The Three-Way HandshakeSYN → SYN-ACK → ACK: how every connection begins≈15 min · 10 steps · 4 questions · guided · after tcp-header-anatomyNot started
- 3TCP-03Sequence & Acknowledgement NumbersHow TCP counts every byte — and never loses track≈15 min · 9 steps · 3 questions · guided · after three-way-handshakeNot started
- 4TCP-04Basic Data TransferFrom an application's write() to segments on the wire≈15 min · 8 steps · 3 questions · guided · after three-way-handshake, sequence-and-ack-numbersNot started
- 5TCP-05The TCP FlagsEight bits that steer every connection≈15 min · 9 steps · 4 questions · guided · after three-way-handshakeNot started
- 6TCP-06Sliding Window & Flow ControlHow a receiver throttles a sender — down to a dead stop≈20 min · 11 steps · 4 questions · guided · after sequence-and-ack-numbersNot started
- 7TCP-07Retransmission After Packet LossTimers, duplicate ACKs, and how TCP refuses to lose data≈20 min · 11 steps · 4 questions · guided · diagnosis lab · after sequence-and-ack-numbers, basic-data-transferNot started
- 8TCP-08Connection TerminationFIN, ACK, FIN, ACK — and the mysterious TIME-WAIT≈15 min · 10 steps · 4 questions · guided · after three-way-handshake, basic-data-transferNot started
- 9TCP-09TCP ResetRST: connection refused, connection destroyed≈10 min · 8 steps · 4 questions · guided · diagnosis lab · after three-way-handshake, connection-terminationNot started
- 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
- 11TCP-11Congestion ControlSlow start, fast retransmit, and why the whole Internet doesn't melt≈20 min · 12 steps · 4 questions · guided · diagnosis lab · after sliding-window-flow-control, retransmission-packet-lossNot started
- 12TCP-12The Silly Window SyndromeRFC 813 · how a correct connection talks itself into tiny, wasteful packets≈15 min · 10 steps · 4 questions · guided · after sliding-window-flow-controlNot started
- 13TCP-13The Nagle AlgorithmRFC 896 · one sentence that tamed the tinygram flood≈15 min · 8 steps · 3 questions · guided · after basic-data-transferNot started
- 14TCP-14Zero-Window ProbesRFC 1122 §4.2.2.17 · how a stalled connection stays alive≈15 min · 9 steps · 3 questions · guided · after sliding-window-flow-controlNot started
- 15TCP-15Congestion CollapseRFC 896 · the prophecy: a network drowning in its own retries≈15 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.
Find the delay in the capture and say what caused it.
TCP ResetDecide from the capture whether the host is unreachable, filtered, or simply not listening.
Troubleshooting Lab: The Site That Never LoadsUsing only the client-side capture, determine why the connection fails.
Congestion ControlFind the moment the sender changed its behaviour and say what triggered it.
Congestion CollapseExplain how sending more produced less, using the capture.
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 fieldChoose 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
A browser opens http://shop.example.test — connection setup only.
HTTP request and responseAfter the handshake, the browser sends a GET and the server answers.
A complete TCP conversationHandshake, HTTP exchange, and a polite four-way close — every common flag in one trace.
Flow control and the zero windowA client uploads 6000 bytes to a slow server whose application stops reading — the window closes to zero, then reopens.
Packet loss and retransmissionThe first data segment is lost in transit. A later segment triggers a duplicate ACK, the retransmission timer fires, and TCP recovers.
Four-way connection terminationBoth sides close politely: FIN, ACK, FIN, ACK — then TIME-WAIT.
Connecting to a closed portNothing is listening on port 80 — the SYN is answered with an immediate RST.
Reset in the middle of a connectionThe server application crashes mid-conversation and aborts with an RST.
Slow start, loss, and fast recoveryA 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 usageA 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 syndromeThe 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 sidesIdentical 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 problemEight keystrokes typed into a remote session with Nagle disabled: one 41-byte-overhead packet per byte of typing.
RFC 896 · The Nagle algorithmThe 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 announcementsClient 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 acknowledgementsA 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 optionThe 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 middleboxThe 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 miniatureA 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 timerThe 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 backoffEvery 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 acknowledgesData 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 windowThe 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 scalingA 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 scalingIdentical 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 directionThe 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 scalingThe 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 tripEvery 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 onlyEight 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 SACKIdentical 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 pathFour 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 spikeThe 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 ruleA 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 RTOIdentical 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 RTOThe 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 cwndcwnd 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 periodA 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 hangsA 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.
The identical sipping application on a historic stack (every tiny window opening advertised) and on an RFC 9293-compliant stack (updates held, crumbs suppressed).
Tinygrams vs the Nagle algorithmEight keystrokes over a 40 ms RTT: one packet per keystroke (Nagle off) versus self-clocked coalescing (Nagle on).
Immediate vs delayed acknowledgementsThe same 4½-segment transfer ACKed two ways: a receipt per segment versus RFC 1122's one-per-two-full-segments with a bounded timer.
Symmetric vs asymmetric MSSThe HTTP exchange with both sides at MSS 1460 versus a constrained server announcing 536 — segment sizes obey the receiver's announcement, per direction.
Congestion collapse vs a patient timerThe same slow, shallow-queued link and the same 17.5 KB transfer — once with an RTO shorter than the queue-inflated RTT (premature retransmissions), once with a conservative timer.
Window scaling vs the 16-bit ceilingThe same 438 KB transfer over the same 200 ms path with 256 KB buffers — once capped by the raw window field, once with Window Scale negotiated.
SACK vs cumulative ACK aloneEight segments, two non-adjacent losses, identical in both runs. The only difference is whether the receiver may describe what it actually holds.
RFC 2988 vs RFC 6298 — the initial RTOThe same lost segment on the same path, timed by the 2000 rules and by today's. Same formulas, one different constant.
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 eachIncluding 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.
Finds the hardware address that owns an IP address on your own wire.
IPv45 lessonsAddresses and forwards packets across networks, with no promises about delivery.
ICMP4 lessonsIP's way of reporting problems and testing whether a host is reachable.
UDP4 lessonsPorts and a checksum. Nothing else, on purpose.
DNS4 lessonsTurns names people can remember into addresses machines can route to.
DHCP5 lessonsHands a machine its address, mask, gateway and resolver when it joins a network.
HTTP3 lessonsRequests and responses carried over a TCP byte stream.
TLS3 lessonsAdds confidentiality, integrity and identity to a TCP connection.
HTTPS2 lessonsNot a separate protocol — HTTP inside TLS inside TCP inside IP inside Ethernet.
OSPF5 lessonsRouters inside one organisation telling each other the shape of the network.
BGP6 lessonsHow separate organisations exchange routes — the protocol that holds the internet together.