Fundamentals 15 min read

Understanding the TCP State Machine: Handshake, Four‑Way Termination, and Practical Experiments

This article explains the TCP three‑way handshake, four‑way termination, and related state transitions, illustrates uncommon scenarios such as simultaneous open and close, discusses half‑open connections, fd‑leak effects, and presents Linux‑based experiments with client.go and server.go code samples.

Qunar Tech Salon
Qunar Tech Salon
Qunar Tech Salon
Understanding the TCP State Machine: Handshake, Four‑Way Termination, and Practical Experiments

The author, a Golang engineer at Qunar, introduces the TCP state machine using clear diagrams and explains how connections transition under the client‑server (C/S) model.

Three‑way handshake : The client initiates a connection by sending SYN, receives SYN+ACK, and replies with ACK, moving both sides to ESTABLISHED . The article lists the key state terms (LISTEN, SYN_SENT, SYN_RECV, ESTABLISHED) and describes the role of sequence numbers (SeqN) and acknowledgments (ACK).

Simultaneous open is shown as a rare case where both peers send SYN at the same time, resulting in a single connection after both SYNs are processed.

Connect success : After the client’s final ACK, connect() returns in blocking mode. The author demonstrates how packet loss (e.g., dropping the ACK) affects the connection and provides three methods to simulate such loss, ultimately using method 3 (dropping the ACK on the server) with the following Linux settings: net.ipv4.tcp_abort_on_overflow=0 and net.core.somaxconn=2 . The experiment uses server.go and client.go source files.

The capture reveals five observations: immediate data transmission after ACK, server’s lack of ACK leading to client retransmission, repeated SYN+ACK retransmissions, client’s retransmitted ACK, and final RST after SYN+ACK retries exceed the limit.

Half‑open connections occur when the server’s accept queue is full and a client disconnects, leaving the server in a state that can cause resource exhaustion or denial‑of‑service attacks. Heartbeat mechanisms (TCP keep‑alive and application‑level heartbeats) are recommended to mitigate this.

Four‑way termination follows the standard FIN‑ACK exchange, with state terms such as FIN_WAIT_1, CLOSE_WAIT, FIN_WAIT_2, LAST_ACK, TIME_WAIT, CLOSING, and CLOSED. The article explains the 2 MSL (Maximum Segment Lifetime) concept, why TIME_WAIT lasts 2 MSL, and its impact on port reuse, mentioning SO_REUSEADDR as a workaround.

Half‑close is described as the ability of one side to stop sending data while still receiving, implemented via the shutdown() call, though most applications simply use close() .

File descriptor (fd) leak experiments show that neglecting close() on the server can leave connections in CLOSE_WAIT, causing delayed handshakes or failures. The author reproduces a Cloudflare‑cited scenario, showing that the server replies with an old ACK, the client discards it, sends RST, and eventually a new three‑way handshake succeeds.

Implementation deviations from the TCP specification are highlighted: many BSD‑derived stacks allow reuse of a four‑tuple in TIME_WAIT if the initial sequence number (ISN) is larger, and some kernels force a FIN_WAIT_2 connection into CLOSED after a timeout (configurable via net.ipv4.tcp_fin_timeout ).

In conclusion, the article summarizes the practical insights gained from the experiments and hints at future topics such as TCP Fast Open, UDP vs. TCP, and QUIC.

State MachineTCPlinuxNetworkingconnection terminationhandshake
Qunar Tech Salon
Written by

Qunar Tech Salon

Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.