What is TCP?
IP delivers packets best-effort — they can vanish, duplicate, or arrive out of order. Almost every program wants a clean stream of bytes instead. TCP is the layer that turns one into the other.
Why it exists
The internet’s foundation, IP, makes a deliberately weak promise: I’ll try to deliver this packet to that address. Not that it will arrive. Not that it will arrive once. Not that it will arrive in the order you sent it. Packets can be dropped by a congested router, duplicated by a misbehaving link, or reordered when two of them take different paths through the network.
Almost no application wants to deal with that. When you write to a socket, you want to push bytes in one end and have the same bytes — all of them, in order, exactly once — come out the other end. That gap, between what IP gives you and what programs want, is what TCP exists to fill.
TCP is old. RFC 793 (1981, Jon Postel ed.) is the original spec; RFC 9293 is the current consolidated one. The core mechanism has survived four decades of hardware change largely intact, which is itself a clue about how well the design holds up.
Why it matters now
Almost every protocol you’ve heard of runs on top of TCP. HTTP (and the HTTPS wrapping it), SSH, SMTP, IMAP, Postgres and MySQL wire protocols, Redis, every git push over SSH or HTTPS. When something is “slow to connect” or “hanging,” it’s almost always TCP behavior leaking up into the application.
It also matters because it’s what the modern alternatives are reacting against. QUIC only makes sense as a story about which specific frictions of TCP needed routing around.
The short answer
TCP = reliable, ordered byte-stream over IP = handshake + sequence numbers + ACKs + retransmits + flow control + congestion control
TCP turns IP’s best-effort packet delivery into a byte stream between two endpoints. It opens the connection with a handshake, numbers every byte it sends, has the receiver acknowledge what it got, retransmits what wasn’t acknowledged, reassembles out-of-order arrivals, and adapts its sending rate to both the receiver’s capacity and the network’s.
How it works
Five mechanisms, each doing one job.
Connection setup — the 3-way handshake. Before any data flows, both sides exchange three messages. The client sends SYN with its initial sequence number. The server replies SYN-ACK: it acknowledges the client’s number and announces its own. The client replies ACK. Why three and not one? Each side needs to tell the other its starting sequence number and confirm the other received that number. The third message is what makes confirmation symmetric.
Reliability — sequence numbers and ACKs. Every byte TCP sends has a number. The receiver sends back ACKs that say “I have everything up through byte N.” If the sender doesn’t see an ACK within a timeout (and modern TCP estimates the path’s RTT and adapts), it retransmits. Duplicates the receiver simply discards. The apparatus turns “packets sometimes vanish” into “the application sees every byte exactly once.”
Ordering. Packets routinely arrive out of order. The receiver buffers them, looks at sequence numbers, and only hands bytes up to the application in order. If byte 1000 arrives before byte 900, it sits in the buffer until 900 arrives.
Flow control. A fast sender talking to a slow receiver could drown it. So every ACK carries a window — “I have room for this many more bytes.” The sender can’t have more than that many bytes unacknowledged in flight. It’s the receiver’s volume knob on the sender.
Congestion control. Distinct from flow control: flow control protects the receiver, congestion control protects the network in between. The sender keeps its own window that grows on clean ACKs and shrinks on loss, reading loss as a hint that some router on the path is full. This gets its own post — see TCP congestion control for AIMD, CUBIC, BBR, and why it exists at all.
Connection teardown. Either side can send FIN (“no more data”); the other ACKs, then sends its own FIN, ACKed back. Closes are independent per direction — half-closed connections are legal.
Show the seams
This is where TCP’s age shows.
- Head-of-line blocking. If segment 5 is lost, segments 6, 7, 8 might already be in the receiver’s buffer — but the application sees nothing until 5 arrives. For one file, fine. For HTTP/2 multiplexing dozens of independent requests over one TCP connection, one lost packet stalls all of them. This is the structural reason QUIC moved to UDP with per-stream loss recovery.
- Handshake latency. A TCP connection costs one RTT before any application byte flows. Layer TLS on top and you pay another one or two RTTs. On a satellite link or congested mobile, it’s painfully visible. QUIC’s combined transport-and-crypto handshake is largely a response.
- Middleboxes calcified the protocol. NATs, firewalls, and load balancers parse TCP headers, and many grew opinions about what they should look like. New TCP options get silently dropped by some hop in the middle. The protocol can’t really evolve on the wire anymore — its own argument for building successors on top of UDP.
Famous related terms
- UDP —
UDP = "send and forget" datagrams over IP— no handshake, no ordering, no retransmits, no flow control. What TCP isn’t. Fine for DNS, voice, games, and anything that prefers “lose it” to “wait for it.” - 3-way handshake —
handshake = SYN → SYN-ACK → ACK— the three messages that exchange and confirm initial sequence numbers before data flows. - TCP congestion control —
congestion control = window that grows on ACKs + shrinks on loss— the mechanism that keeps the shared internet from collapsing when many senders compete. - QUIC —
QUIC = UDP + TLS 1.3 + per-stream reliability + connection IDs— the TCP successor for browser traffic, designed to fix exactly the seams above. - TLS —
TLS ≈ encryption + identity on top of TCP— what runs above TCP to make connections private and authenticated. - Head-of-line blocking —
HoL = one stall halts the whole stream— the in-order delivery property that becomes a liability under multiplexing.
Going deeper
- W. Richard Stevens, TCP/IP Illustrated, Volume 1. The classic. The mechanism explanations have aged better than almost any networking book.
- RFC 9293 — the current consolidated TCP specification; supersedes RFC 793 and a long pile of patches.
- RFC 793 (1981) is still worth reading once for historical reasons — short, and the design intent is unusually clear.
- Cloudflare’s engineering blog has a steady stream of good TCP-edge-case explainers if you want production stories rather than spec text.