Why Does TCP Keep Connections in TIME_WAIT? Uncover the Hidden Risks
This article explains the TCP state machine, details the four-way handshake, analyzes why the TIME_WAIT state lasts for two MSL intervals, and illustrates two critical problems caused by delayed packets and missing ACKs, providing examples and code snippets for deeper understanding.
TCP State Machine
The diagram below shows the state transitions after both parties have established a TCP connection.
The side that actively initiates connection closure enters the TIME_WAIT state, while the passive side enters CLOSE_WAIT .
A side in TIME_WAIT mainly wastes two resources:
Port number (primary resource)
System resources (file descriptors, memory, CPU, threads) – negligible on modern hardware
Two Issues
Consider the classic “four‑handshake” when the client actively closes the connection:
First handshake: client sends FIN and moves to FIN_WAIT_1.
Second handshake: server receives FIN, enters CLOSE_WAIT, sends ACK; client receives ACK and moves to FIN_WAIT_2.
Third handshake: server sends FIN and enters LAST_ACK.
Fourth handshake: client receives server FIN, enters TIME_WAIT, sends ACK, server moves to CLOSED.
After waiting for 2 MSL, client finally enters CLOSED.
The client must keep the TIME_WAIT state for 2 MSL (about 2 minutes on Linux 5.0, see code below):
#define TCP_TIMEWAIT_LEN (60*HZ) /* about 60 seconds */Why two MSL? Because both the sender and receiver must consider the maximum segment lifetime (MSL) for data and ACK packets, totaling two MSL.
The mechanism prevents two problems:
Prevent the passive side from receiving delayed data belonging to a new connection that reuses the same four‑tuple.
Prevent the passive side from missing an ACK for its FIN, which could cause a new connection to be rejected with RST.
First Issue
Prevent the passive side from receiving delayed data on a new connection with the same four‑tuple.
In short, old delayed packets could interfere with a newly created connection that reuses the same source/destination IPs and ports.
Scenario:
Client receives a delayed packet A (seq = 1001) after it has closed the old connection.
If the client does not stay in TIME_WAIT, it would move directly to CLOSED after the fourth handshake.
When the client later opens a new connection that reuses the same ports, packet A arrives on the new connection, potentially corrupting the data stream.
Keeping the connection in TIME_WAIT for 2 MSL ensures such delayed packets are discarded.
If a delayed packet arrives after the 2 MSL window and its sequence falls within the new connection’s receive window, the outcome depends on encryption:
Unencrypted data may be injected into the application stream.
Encrypted traffic (e.g., HTTPS) will fail integrity checks and be dropped.
Second Issue
Prevent the passive side from missing an ACK for its FIN , which could cause a new connection to be rejected with RST .
In short, if the ACK for the fourth handshake is lost, the server remains in LAST_ACK and may treat a subsequent SYN with the same four‑tuple as part of the old connection, replying with RST and rejecting the new connection.
Scenario:
Client’s ACK in the fourth handshake is lost; server stays in LAST_ACK.
If the client does not enter TIME_WAIT, it moves to CLOSED while the server still thinks the connection is alive.
The client opens a new connection reusing the same ports; the server receives the new SYN and, believing the old connection is still valid, replies with RST, aborting the new connection.
With TIME_WAIT, the client waits 2 MSL, giving the server enough time to transition to CLOSE or to retransmit FIN and receive the missing ACK.
Problem Scenarios
Large numbers of TIME_WAIT connections appear during high‑concurrency stress testing, where thousands of short‑lived connections are created rapidly.
Example command on Linux:
$ netstat -ant | grep TIME_WAIT
# Sample output
tcp6 0 0 1.1.1.1:443 127.0.0.1:59490 TIME_WAIT
...Further discussion on TCP tuning for high‑performance networking will be covered in a future article.
Reflection
If many connections are stuck in CLOSE_WAIT, what could be the cause and how can it be resolved?
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Linux
Focused on sharing Linux/Unix content, covering fundamentals, system development, network programming, automation/operations, cloud computing, and related professional knowledge.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
