Before any data flows, a TCP client and server exchange three segments — SYN, SYN-ACK, ACK — to agree on starting sequence numbers and confirm both sides are ready.
TCP is connection-oriented: before exchanging data, the client and server run a three-segment handshake. The client sends SYN with its initial sequence number. The server replies SYN-ACK, acknowledging the client's number and sending its own. The client sends ACK, acknowledging the server's number. After this, both sides are ESTABLISHED and can exchange data reliably, using sequence and acknowledgment numbers to detect loss and reordering.
Step through tcp three-way handshake live, one move at a time — this becomes a fully interactive visualizer.
Coming soonSYN flag set and a randomly chosen initial sequence number (ISN), e.g. seq=300. Client moves from CLOSED to SYN_SENT.LISTEN to SYN_RCVD — it now knows a client wants to connect.SYN and ACK: ack = client_seq + 1 confirms the client's SYN, and a fresh seq is the server's own ISN.ESTABLISHED — it doesn't need to wait for anything further before it's safe to send.ACK with ack = server_seq + 1, confirming the server's ISN.ESTABLISHED. Both sides now agree on starting sequence numbers, and data can flow in either direction.// Client state = CLOSED send(SYN, seq: clientIsn) state = SYN_SENT on receive(SYN, ACK, seq: serverIsn, ack: clientIsn + 1): state = ESTABLISHED send(ACK, seq: clientIsn + 1, ack: serverIsn + 1) // Server state = LISTEN on receive(SYN, seq: clientIsn): state = SYN_RCVD send(SYN, ACK, seq: serverIsn, ack: clientIsn + 1) on receive(ACK, ack: serverIsn + 1): state = ESTABLISHED
| TCP | UDP | |
|---|---|---|
| Connection setup | Three-way handshake required before data flows | None — the first packet just goes |
| Delivery guarantee | Reliable — lost segments are detected and retransmitted | Best-effort — a lost packet is simply gone |
| Ordering | Guaranteed — sequence numbers reorder segments on arrival | Not guaranteed — packets may arrive out of order |
| Overhead | Higher — handshake latency, headers, acknowledgments | Lower — no setup, no tracking state |
| Typical use | Web pages, file transfer, email — correctness matters | Video calls, DNS, gaming — speed matters more than a dropped packet |
TCP promises reliable, ordered, exactly-once delivery of a byte stream, over an unreliable network. Making that promise requires both sides to first agree on a shared starting point — an initial sequence number each side uses to number the bytes it sends — before either can meaningfully talk about 'received up to byte N' or 'byte N was lost, please resend.' The handshake is that agreement, negotiated before a single byte of real data is sent.
Each side needs to both propose its own sequence number and confirm the other side's — that's naturally four actions (client SYN, server ACK, server SYN, client ACK). TCP collapses the server's ACK and SYN into one segment, since they're headed to the same place at the same time anyway, bringing the total to three. Two segments wouldn't be enough: the client would never confirm it received the server's sequence number, so the server could never be sure the client is ready.
The initial sequence numbers exchanged here aren't just a formality — every byte of real data sent afterward is numbered starting from that point. If a segment is lost, the receiver's acknowledgment number will stay stuck at the last byte it successfully received in order, signaling the sender to retransmit. Reordered segments are put back in order using these same numbers before the application ever sees the data. The handshake is where this whole accounting scheme begins.
Because a server allocates some memory to track a connection as soon as it receives a SYN (moving to SYN_RCVD), an attacker who sends many SYNs with no intention of ever completing the handshake can exhaust that memory — a classic denial-of-service technique called a SYN flood. Defenses like SYN cookies let a server avoid committing memory until the final ACK actually arrives, encoding the state it needs directly into the SYN-ACK's sequence number instead of storing it.
SYN → SYN+ACK → ACK · Client: CLOSED → SYN_SENT → ESTABLISHED · Server: LISTEN → SYN_RCVD → ESTABLISHED · ack = seq + 1 acknowledges a sequence number · Client reaches ESTABLISHED one segment before the server · 1.5 round trips before data can flowBecause exactly three segments are exchanged: SYN, then SYN-ACK, then ACK. The server's acknowledgment and its own SYN are combined into that single middle segment, which is what keeps the count at three instead of four.
TCP retransmits: if the client doesn't receive a SYN-ACK within a timeout, it resends the SYN. If the server's SYN-ACK is lost, the client will retransmit its SYN, prompting the server to resend the SYN-ACK. The handshake simply doesn't complete until all three segments have successfully arrived.
No — UDP is connectionless. There's no setup exchange and no shared connection state; the first UDP packet just travels to its destination with no guarantee it arrives, and no mechanism to notice if it doesn't.
Share what clicked for you and see notes from other learners on this topic.
Coming soon