TCP¶
Transmission Control Protocol provides reliable, ordered, connection-oriented byte-stream delivery.
What TCP guarantees: - Reliability: lost segments detected via ACKs and retransmitted - Ordering: segments delivered to application in send order - No duplication: duplicate segments discarded - Connection-oriented: state established before data transfer
What TCP costs: - Connection establishment: 1 RTT for handshake - Retransmission timeout: lost packet pauses sender until retransmit - Flow control overhead: receiver advertises window size in every ACK - Head-of-line blocking: lost packet blocks all subsequent data — TCP-level HOL, not fixed by HTTP/2
Three-way handshake:
- Client → Server: SYN(seq=x) — client announces initial sequence number x
- Server → Client: SYN+ACK(seq=y, ack=x+1) — server ACKs client's seq, announces own seq y
- Client → Server: ACK(seq=x+1, ack=y+1) — client ACKs server's seq
Three steps are necessary because sequence numbers must be established in both directions. Two steps would leave the server with no confirmation the client received its ISN.
ISN (Initial Sequence Number): randomly chosen to prevent TCP segment injection attacks.
Four-way teardown: FIN → ACK → FIN → ACK. Steps 2 and 3 are separate because the responder may have data left to send after receiving the initiator's FIN (half-close).
TIME_WAIT state:
After the initiator sends the final ACK, it waits 2×MSL (60–120s) to: ensure the final ACK arrives, prevent old segments from a previous connection confusing a new connection on the same port. Causes port exhaustion at very high connection rates. Mitigations: SO_REUSEADDR, SO_REUSEPORT.
Flow control (sliding window):
Receiver advertises receive buffer space in every ACK. Sender keeps at most window_size bytes unACKed in flight. Prevents fast sender from overwhelming slow receiver.
Congestion control: TCP infers congestion from packet loss (classic) or RTT increase (BBR). - Slow start: CWND doubles each RTT until ssthresh - Congestion avoidance: CWND grows by 1 MSS per RTT - On triple dup-ACK (loss): ssthresh = CWND/2, CWND = ssthresh (fast recovery) - On timeout: CWND = 1 MSS, restart slow start
BBR estimates bottleneck bandwidth and RTT — better for high-bandwidth, high-latency links.
Common pitfall¶
Opening a new TCP connection per request (instead of reusing one via
keep-alive or a connection pool) pays the full
1-RTT handshake cost — plus a TLS handshake on top of it, for HTTPS —
on every single request, even to the same server. This is invisible
in local testing (RTT to localhost is near zero) and becomes a very
real latency tax the moment real network RTT enters the picture — see
Request Lifecycle for exactly where this cost
lands in the full request timeline.