JOVANA
Explore Library Glossary Getting Started Three Levels Fields How it works Mission
Join the mission
All guides

The Three-Way Handshake and Tearing Down

Before TCP can hand you a perfect byte stream, both sides have to agree that a conversation is even happening and where its counting starts. Here is the famous opening ritual, the calmer closing one, and the quietly important state that lingers after goodbye.

Why a connection needs an opening at all

In the previous guide you saw how TCP manufactures reliable delivery out of an unreliable network using sequence numbers, acknowledgments, and timers. But that whole machine quietly assumed something we never justified: that both ends had already agreed they were in a conversation, and that they agreed on where the counting starts. A sequence number only means anything if the receiver knows which number the sender called byte one. The job of the opening handshake is to establish exactly that shared starting point, on both sides, before a single byte of your data moves.

It helps to remember that the transport layer lives at the very edges of the network. No router in the middle keeps any record that your TCP connection exists; the connection is purely a shared agreement held in the memory of the two end hosts, an entry in a table at each end. So opening a connection does not mean carving a path through the network. It means the two ends performing a short ritual that leaves each of them holding a matching record of the other. Think of two people on a phone line who have never spoken: before either says anything important, they confirm the line works in both directions and they introduce themselves.

Can you hear me? Yes, can you?

The opening ritual is the three-way handshake, and the everyday version is exactly the back-and-forth you would do on a bad phone line: 'Can you hear me?' — 'Yes, can you?' — 'Yes.' Three messages, because that is the smallest number that lets BOTH ends confirm that traffic flows in BOTH directions. Two would only prove one direction works. The three TCP messages carry control flags in the TCP segment header named SYN (synchronize) and ACK (acknowledge), and the exchange is named after them: SYN, SYN-ACK, ACK.

Here is the crucial part that the phone analogy hides. The real purpose of those first SYN messages is to carry each side's initial sequence number — the number each end has privately chosen as the label for the first byte it will ever send. The client picks some starting number, say x, and announces it in its SYN. The server picks its own, say y, and announces it in the SYN-ACK while also acknowledging the client's x. The final ACK confirms the server's y. After three messages, each side knows both numbers, and the synchronized counting that the whole reliability machine depends on is now in place. That is why the SYN flag literally stands for synchronize.

  CLIENT                                         SERVER
    |                                              |
    |   1.  SYN,  seq = x                          |
    | -------------------------------------------> |   "my counting starts at x"
    |                                              |
    |   2.  SYN-ACK,  seq = y,  ack = x + 1        |
    | <------------------------------------------- |   "mine starts at y; I heard x"
    |                                              |
    |   3.  ACK,  ack = y + 1                       |
    | -------------------------------------------> |   "I heard y; let's talk"
    |                                              |
    |   ====== connection established both ways ====|
The SYN, SYN-ACK, ACK exchange. Each ACK number is the other side's sequence number plus one, meaning 'I have everything up to here; send me that byte next.' After message 3 both ends agree the link works in both directions and both know where counting starts.

Why not just start at zero?

A natural question: if both ends just need a starting point, why not always begin at byte 0? The answer is one of those honest details that reveals how messy the real network is. Suppose every connection started counting at 0. Now imagine an old packet from a previous connection between the same two machines and the same two ports is still wandering the network, delayed in some queue, and finally arrives during a brand-new connection. With predictable sequence numbers it could be mistaken for valid current data and silently corrupt the stream. Choosing a fresh, hard-to-guess initial sequence number for each connection makes such a stale ghost almost certainly fall outside the new connection's accepted number range, so it is rejected.

There is a famous dark side worth knowing. Notice that when the server receives a SYN and replies with SYN-ACK, it must allocate a little memory to remember this half-open connection while it waits for the final ACK. An attacker can flood a server with SYNs from forged addresses and never send the final ACK, piling up half-open connections until the server's table fills and it can no longer accept honest callers. That is a SYN flood, a classic denial-of-service attack, and it falls straight out of how the handshake works. The standard defense, SYN cookies, cleverly lets the server avoid storing state until the handshake actually completes.

Saying goodbye: tearing the connection down

Opening was a careful three-step ritual; closing is calmer, and it reveals something important about TCP's nature. A TCP connection is really two independent one-way byte streams glued together, so tearing it down happens one direction at a time. Either side can announce 'I am done sending' by setting a FIN (finish) flag in a segment, while still remaining willing to receive whatever the other side has left to send. Only when BOTH directions have been closed and acknowledged is the connection truly over. Think of a phone call where one person says 'okay, I have nothing more to add' but stays on the line, politely listening, until the other has also finished.

  1. The side that wants to close (say the client) sends a segment with the FIN flag set: 'I have no more data to send.' It keeps its receive side open.
  2. The other side (the server) acknowledges that FIN with an ACK. The client-to-server direction is now closed, but the server-to-client direction is still open and may keep sending.
  3. When the server has also finished sending, it sends its own FIN: 'now I am done too.'
  4. The client acknowledges the server's FIN with a final ACK. Both directions are now closed; the connection is logically over.

Notice the symmetry with the open: opening synchronized two starting numbers in three messages; closing acknowledges two endings, usually in four (FIN, ACK, FIN, ACK), because the two directions finish at different times. The control flags SYN and FIN bookend the conversation, and because each consumes one sequence number, even the act of opening and closing is counted and acknowledged with the same reliable machinery as your actual data. TCP does not bolt connection management onto the side; it expresses it in the very same numbering scheme.

The quiet wait after goodbye

There is one last subtlety that trips up almost everyone who watches real connections close. The side that sent the final ACK does not immediately forget the connection. Instead it parks in a special TIME-WAIT state for a while, typically a couple of minutes, holding onto the connection's identity even though no data flows. It feels wasteful, even like a bug, but it is doing two genuinely useful jobs. The whole point is to clean up the network gracefully rather than yank the connection away the instant the last message is sent.

First, that final ACK might get lost. If it does, the other side's FIN will time out and be retransmitted, and the only host still remembering enough to answer it is the one sitting in TIME-WAIT. Forget too soon and you would leave the peer stuck. Second, TIME-WAIT lets any stray, delayed packets from this connection drain out of the network and expire before the same address-and-port pair could be reused for a new connection — the very stale-ghost problem that unpredictable initial sequence numbers also guard against. Waiting roughly twice the maximum time a packet can survive in the network guarantees the old ducks are all gone before a new flock arrives.

Where this leaves you

You now have the full life of a TCP connection in one piece: a three-way handshake opens it by synchronizing both sides' initial sequence numbers, a graceful exchange of FINs closes each direction in turn, and a patient TIME-WAIT mops up afterward. Every part of this ritual exists to serve the reliable byte stream you studied in the previous guide; the handshake is what makes those sequence numbers mean something in the first place.

One honest reminder before the final guide of this rung. Everything here is about correctness and tidiness, not speed: even a flawless connection costs you a full round trip just to open before any data flows, and a slow handshake on a high-latency link is felt as lag. That setup cost is exactly the kind of overhead that newer designs attack — QUIC, which we will meet later, folds the connection and encryption setup together to save round trips. But before optimizing, the last guide of this rung tackles two problems that arise once data really is flowing: how a fast sender avoids overwhelming a slow receiver, and the surprising way a single lost segment can stall an entire stream — head-of-line blocking.