Computer Networking

TCP

A reliable ordered byte stream over an unreliable network: the handshake, sequence numbers, acknowledgments, loss recovery, flow control, congestion control, head-of-line blocking and the connection lifecycle.

The question this module answers · How do you build a reliable stream out of packets that can be lost, duplicated and reordered?
TCP: A Reliable Ordered Byte Stream over an Unreliable Network

IP loses, duplicates, reorders and delays packets and says nothing about it; TCP turns that into a connection over which bytes arrive exactly once, in order, at a rate the receiver and the network can absorb — by numbering every byte, acknowledging what arrived, retransmitting what did not, and windowing what is in flight — and it hands the application a stream, not messages.

The Three-Way Handshake
▶ interactive

SYN, SYN-ACK, ACK: three segments in which each side proposes its initial sequence number and hears the other’s acknowledged, options are agreed, and the server moves the connection from a half-open queue to the accept queue — one full round trip before a single byte of data, which is the cost every short connection pays.

Sequence Numbers, ACKs and Reassembly
▶ interactive

Every byte in a TCP stream has a number; a segment carries the number of its first byte, an ACK carries the number of the next byte the receiver wants, and out-of-order segments wait in a reassembly buffer until the hole before them is filled — which is why numbers are byte offsets, why cumulative ACKs cannot describe a gap, and why SACK exists.

Packet Loss: Duplicate ACKs, Fast Retransmit and the RTO
▶ interactive

When a segment is lost, TCP learns it either from three duplicate ACKs (fast, one round trip) or from a retransmission timer (slow, at least 200 ms on Linux and doubling), retransmits, and — because loss is also read as congestion — cuts its sending rate; the application sees only a stall, and a loss rate of 1% can cost most of a link’s throughput.

Flow Control: The Receive Window
▶ interactive

The receiver tells the sender, in every ACK, how many more bytes it has room for; the sender never has more than that in flight; when the application stops reading, the buffer fills, the window goes to zero and the sender stops — so a slow consumer throttles a fast producer all the way back through the network, which is backpressure by design.

Congestion Control: Protecting the Network
▶ interactive

No router tells a sender how much capacity is left, so the sender probes: it keeps a congestion window that grows exponentially, then linearly, and shrinks sharply when loss or an ECN mark says a queue is full — the sawtooth that shares links fairly, and the mechanism that CUBIC and BBR each implement with different signals.

Head-of-Line Blocking
▶ interactive

Because TCP delivers bytes strictly in order, one lost segment holds back every byte behind it even when those bytes have already arrived — a property that HTTP/1.1 dodged with six parallel connections, that HTTP/2’s multiplexing made worse by putting every request on one stream, and that HTTP/3 addresses with QUIC’s independent streams, without eliminating ordering costs inside a stream or in the application.

The Connection Lifecycle: Close, Reset, TIME_WAIT, CLOSE_WAIT
▶ interactive

A TCP connection is a state machine on both ends: established by the handshake, torn down by a FIN in each direction, aborted by RST — and the side that closes first sits in TIME_WAIT for a minute holding the port pair, while a side that never calls close() sits in CLOSE_WAIT forever; these states explain ECONNRESET, ephemeral-port exhaustion, descriptor leaks, and why many short connections are expensive.