Episode 1 — Fundamentals / 1.3 — Internet Protocols

1.3.b — How Connection is Established Using TCP (Three-Way Handshake)

In one sentence: Before a single byte of your webpage can flow, the client and server must synchronize by exchanging three special messages — SYN, SYN-ACK, ACK — a ritual called the three-way handshake that opens a reliable, two-way communication channel.

Navigation: ← 1.3.a — What is TCP · 1.3.c — What is UDP →


Table of Contents


1. Why a Handshake?

TCP is connection-oriented — both sides must agree they are ready before data flows. The handshake accomplishes three things:

PurposeWhat it ensures
ReachabilityBoth sides confirm the other is alive and listening
SynchronizationBoth sides exchange initial sequence numbers (ISNs) so they can track every byte
Parameter agreementBoth sides negotiate options: Maximum Segment Size (MSS), Window Scale, SACK support, timestamps

Without a handshake, the sender would blast data into the void with no idea whether the receiver exists, is ready, or speaks the same "version" of TCP.


2. The Three Steps — Explained

  CLIENT                                              SERVER
  (wants to connect)                                  (listening on a port)
    │                                                    │
    │                                                    │
    │  ┌──────────────────────────────────────────────┐  │
    │  │  STEP 1: SYN                                 │  │
    │  │  "Hey, I want to talk. My starting number    │  │
    │  │   is X. Are you there?"                      │  │
    │  └──────────────────────────────────────────────┘  │
    │  ───────────────────────────────────────────────►  │
    │                                                    │
    │                                                    │
    │  ┌──────────────────────────────────────────────┐  │
    │  │  STEP 2: SYN-ACK                             │  │
    │  │  "Yes, I'm here! I acknowledge your X.       │  │
    │  │   My starting number is Y."                  │  │
    │  └──────────────────────────────────────────────┘  │
    │  ◄──────────────────────────────────────────────  │
    │                                                    │
    │                                                    │
    │  ┌──────────────────────────────────────────────┐  │
    │  │  STEP 3: ACK                                 │  │
    │  │  "Got it! I acknowledge your Y.              │  │
    │  │   Let's go!"                                 │  │
    │  └──────────────────────────────────────────────┘  │
    │  ───────────────────────────────────────────────►  │
    │                                                    │
    │  ═══════════ CONNECTION ESTABLISHED ════════════   │
    │                                                    │
    │  Data can now flow in both directions              │
StepWho sendsFlag(s) setWhat it carries
1. SYNClient → ServerSYNClient's Initial Sequence Number (ISN), MSS, window scale, options
2. SYN-ACKServer → ClientSYN + ACKServer's ISN, acknowledgment of client's ISN (client ISN + 1), server's MSS/options
3. ACKClient → ServerACKAcknowledgment of server's ISN (server ISN + 1); can include data in some cases

3. Sequence Numbers — What Gets Synchronized

Every byte in a TCP connection has a sequence number. The handshake establishes where each side's numbering starts.

  CLIENT picks ISN = 1000                SERVER picks ISN = 5000

  Step 1: SYN
    Client → Server
    seq = 1000, SYN flag set
    "My stream will start at byte 1000"

  Step 2: SYN-ACK
    Server → Client
    seq = 5000, ack = 1001, SYN + ACK flags set
    "My stream starts at 5000. I expect your next byte to be 1001"

  Step 3: ACK
    Client → Server
    seq = 1001, ack = 5001, ACK flag set
    "I expect your next byte to be 5001. We're synchronized!"

  ═══════════════════════════════════════════════════════
  After handshake:
  • Client sends data starting at seq 1001
  • Server sends data starting at seq 5001
  • Every byte is tracked; nothing is lost

Why random ISNs? If ISNs always started at 0, an attacker could predict sequence numbers and inject fake packets. Random ISNs make TCP sequence prediction attacks much harder.


4. Real-World Analogy — The Phone Call

┌─────────────────────────────────────────────────────────────────┐
│                     THE PHONE CALL ANALOGY                       │
│                                                                  │
│  You (Client)                     Friend (Server)                │
│                                                                  │
│  Step 1 — RING RING              "Hey, can you hear me?"        │
│           (SYN)                                                  │
│                                                                  │
│  Step 2 — "Yes I can hear you!   Can YOU hear ME?"              │
│           (SYN-ACK)                                              │
│                                                                  │
│  Step 3 — "Yes! I hear you too.  Let's talk!"                   │
│           (ACK)                                                  │
│                                                                  │
│  ═══════ CONVERSATION BEGINS ═══════                            │
│                                                                  │
│  Both sides CONFIRMED they can hear each other.                  │
│  A two-step handshake (just SYN + SYN-ACK) wouldn't work:       │
│  the server wouldn't know the client received its response.      │
└─────────────────────────────────────────────────────────────────┘

Why not two steps? With only SYN and SYN-ACK, the server sends its ISN but never gets confirmation that the client received it. The third step (ACK) closes the loop — both sides know the other received their ISN.


5. What Happens at Each Step (Technical Detail)

Step 1: Client sends SYN

TCP Segment:
  Source Port:      52431 (ephemeral)
  Destination Port: 443 (HTTPS)
  Sequence Number:  1000 (random ISN)
  Ack Number:       0 (not set yet)
  Flags:            SYN = 1
  Window Size:      65535
  Options:          MSS=1460, Window Scale=7, SACK Permitted, Timestamps
  • Client transitions from CLOSED to SYN_SENT state
  • The SYN flag consumes one sequence number (so the next byte will be 1001)

Step 2: Server sends SYN-ACK

TCP Segment:
  Source Port:      443
  Destination Port: 52431
  Sequence Number:  5000 (server's random ISN)
  Ack Number:       1001 (client's ISN + 1)
  Flags:            SYN = 1, ACK = 1
  Window Size:      65535
  Options:          MSS=1460, Window Scale=7, SACK Permitted, Timestamps
  • Server transitions from LISTEN to SYN_RECEIVED state
  • The ack = 1001 says: "I received everything up to byte 1000; send me byte 1001 next"

Step 3: Client sends ACK

TCP Segment:
  Source Port:      52431
  Destination Port: 443
  Sequence Number:  1001
  Ack Number:       5001 (server's ISN + 1)
  Flags:            ACK = 1
  Window Size:      65535
  • Client transitions to ESTABLISHED state
  • Upon receiving this, server also transitions to ESTABLISHED
  • Data transfer can begin immediately (client can even piggyback data on this ACK)

6. TCP Flags Used in the Handshake

FlagFull namePurpose
SYNSynchronize"I want to start a connection; here's my ISN"
ACKAcknowledge"I confirm receipt of your data up to this sequence number"
FINFinish"I'm done sending data" (used in connection close, not handshake)
RSTReset"Something is wrong; abort the connection immediately"
PSHPush"Deliver this data to the application immediately"
URGUrgent"This segment contains urgent data" (rarely used)

During the handshake, only SYN and ACK are used. The combination SYN + ACK (both flags set) in step 2 is why we call it "SYN-ACK."


7. Timing and Performance

How long does a handshake take?

The handshake requires one full round trip (1 RTT):

  Time ──────────────────────────────────────────────►

  Client                                    Server
    │                                          │
    │── SYN ────────────────────────────────►  │  ½ RTT
    │                                          │
    │  ◄──────────────────────────── SYN-ACK ──│  ½ RTT
    │                                          │
    │── ACK ────────────────────────────────►  │  ½ RTT (+ data can start)
    │                                          │
    Total: ~1.5 RTT before data flows
    (but only 1 RTT before client can start sending data)
Server locationTypical RTTHandshake cost
Same data center< 1 msNegligible
Same country10–40 ms10–40 ms
Cross-continent80–150 ms80–150 ms
Around the world200–300 ms200–300 ms

Why this matters for web performance

For an HTTPS page load, you pay:

  1. DNS lookup (variable)
  2. TCP handshake (1 RTT)
  3. TLS handshake (1 additional RTT with TLS 1.3)
  4. HTTP request + response (1 RTT)

That's 3 RTTs minimum before any data arrives. With a 150 ms RTT, that's 450 ms of just setup. This is why:

  • CDNs reduce RTT by placing servers closer
  • HTTP/2 reuses one TCP connection for many requests
  • HTTP/3 (QUIC) combines transport and TLS handshake to save round trips

8. What Can Go Wrong

ProblemWhat happensResult
SYN lostClient sends SYN, never gets SYN-ACKClient retries after timeout (typically 1s, then 2s, 4s... exponential backoff)
SYN-ACK lostServer responded but client never got itClient retries SYN; server may retransmit SYN-ACK
ACK lostServer waits in SYN_RECEIVEDServer retransmits SYN-ACK; client resends ACK
Server not listeningNo application on that portServer responds with RST — connection refused
Firewall blocksSYN packet dropped by firewallClient sees timeout — ERR_CONNECTION_TIMED_OUT
Port unreachableServer sends ICMP port unreachableClient sees connection refused immediately

9. SYN Flood Attack

A SYN flood is a denial-of-service (DoS) attack that exploits the handshake.

  ATTACKER                                  SERVER
    │                                          │
    │── SYN (fake source IP) ────────────────►│  Server allocates memory
    │── SYN (fake source IP) ────────────────►│  for half-open connection
    │── SYN (fake source IP) ────────────────►│
    │── SYN (fake source IP) ────────────────►│  Server's connection table
    │── SYN (fake source IP) ────────────────►│  fills up...
    │── SYN ... thousands more ... ──────────►│
    │                                          │
    │  Server waits for ACKs that never come   │  SERVER OVERWHELMED
    │  Legitimate users can't connect           │  (out of memory/slots)

Defenses

DefenseHow it works
SYN cookiesServer encodes state in the SYN-ACK's sequence number instead of storing it; no memory allocated until the ACK returns
Rate limitingLimit SYN packets per source IP per second
Firewalls / DDoS protectionCloud services (Cloudflare, AWS Shield) filter malicious SYN floods before they reach the server
Shorter timeoutsReduce the time half-open connections linger

10. Connection Termination — The Four-Way Close

When the conversation is done, TCP uses a four-way handshake to close gracefully:

  CLIENT                                    SERVER
    │                                          │
    │  FIN ──────────────────────────────────► │  "I have no more data to send"
    │                                          │
    │  ◄────────────────────────────────── ACK │  "Acknowledged"
    │                                          │
    │                  (server may still send   │
    │                   remaining data)         │
    │                                          │
    │  ◄────────────────────────────────── FIN │  "I'm done too"
    │                                          │
    │  ACK ──────────────────────────────────► │  "Acknowledged. Connection closed."
    │                                          │
    │  ══════ CONNECTION FULLY CLOSED ═══════  │

Why four steps instead of three? Because TCP is full-duplex — each direction closes independently. The server might still have data to send after the client says "I'm done." So each side sends its own FIN and receives its own ACK.

TIME_WAIT state

After the final ACK, the client enters TIME_WAIT for 2 × MSL (Maximum Segment Lifetime, typically 60 seconds). This ensures:

  • Late-arriving packets from the old connection don't get confused with a new one
  • The server's final FIN can be re-acknowledged if the ACK was lost

11. Key Takeaways

  1. The three-way handshake (SYN → SYN-ACK → ACK) establishes a TCP connection before any data flows.
  2. Each side shares a random Initial Sequence Number (ISN) so both can track every byte in the stream.
  3. The handshake costs 1 RTT — a significant performance factor for distant servers.
  4. SYN floods exploit the handshake by overwhelming the server with half-open connections; SYN cookies are the primary defense.
  5. Connection termination uses a four-way close (FIN → ACK → FIN → ACK) because each direction closes independently.
  6. Understanding the handshake explains why CDNs (closer servers = shorter RTT) and HTTP/2 (one connection for many requests) improve performance.

12. Explain-It Challenge

Without looking back, explain in your own words:

  1. Draw the three-way handshake on paper with arrows and label each step (SYN, SYN-ACK, ACK).
  2. Why does TCP need three steps instead of two?
  3. What is an Initial Sequence Number and why is it randomized?
  4. What is a SYN flood attack and how do SYN cookies defend against it?
  5. How does the four-way close differ from the three-way handshake, and why?

Navigation: ← 1.3.a — What is TCP · 1.3.c — What is UDP →