1. TCP 三次握手(Three-Way Handshake)
三次握手用于建立 TCP 连接,确保客户端和服务器双方都准备好进行通信。
步骤:
-
第一次握手(SYN):
-
客户端向服务器发送一个
SYN(Synchronize)包,表示请求建立连接。 -
包中包含客户端的初始序列号(
seq = x)。 -
客户端进入
SYN_SENT状态。
-
-
第二次握手(SYN + ACK):
-
服务器收到
SYN包后,向客户端发送一个SYN + ACK包,表示同意建立连接。 -
包中包含服务器的初始序列号(
seq = y)和对客户端SYN的确认号(ack = x + 1)。 -
服务器进入
SYN_RECEIVED状态。
-
-
第三次握手(ACK):
-
客户端收到
SYN + ACK包后,向服务器发送一个ACK(Acknowledgment)包,表示确认连接已建立。 -
包中包含对服务器
SYN的确认号(ack = y + 1)。 -
客户端和服务器都进入
ESTABLISHED状态,连接建立完成。
-
图示:
客户端 服务器| || SYN (seq=x) || -------------------------------> || || SYN + ACK (seq=y, ack=x+1) || <------------------------------- || || ACK (ack=y+1) || -------------------------------> || |
为什么需要三次握手?
-
确保双方都能收发数据:通过三次握手,客户端和服务器都能确认对方的发送和接收能力。
-
防止旧的重复连接请求:如果客户端发送的
SYN包是延迟的旧包,服务器可以通过客户端的ACK包判断是否为有效连接。
2. TCP 四次挥手(Four-Way Handshake)
四次挥手用于关闭 TCP 连接,确保双方都完成数据传输并安全关闭连接。
步骤:
-
第一次挥手(FIN):
-
客户端(或服务器)发送一个
FIN(Finish)包,表示请求关闭连接。 -
包中包含序列号(
seq = u)。 -
发送方进入
FIN_WAIT_1状态。
-
-
第二次挥手(ACK):
-
接收方收到
FIN包后,发送一个ACK包,表示确认收到关闭请求。 -
包中包含确认号(
ack = u + 1)。 -
接收方进入
CLOSE_WAIT状态,发送方进入FIN_WAIT_2状态。
-
-
第三次挥手(FIN):
-
接收方完成数据处理后,发送一个
FIN包,表示同意关闭连接。 -
包中包含序列号(
seq = w)。 -
接收方进入
LAST_ACK状态。
-
-
第四次挥手(ACK):
-
发送方收到
FIN包后,发送一个ACK包,表示确认关闭连接。 -
包中包含确认号(
ack = w + 1)。 -
发送方进入
TIME_WAIT状态,等待一段时间后关闭连接。 -
接收方收到
ACK包后,关闭连接。
-
图示:
客户端 服务器| || FIN (seq=u) || -------------------------------> || || ACK (ack=u+1) || <------------------------------- || || FIN (seq=w) || <------------------------------- || || ACK (ack=w+1) || -------------------------------> || |
为什么需要四次挥手?
-
双向关闭:TCP 连接是全双工的,双方需要分别关闭自己的发送通道。
-
确保数据完整性:接收方需要时间处理未完成的数据,并在确认完成后发送
FIN包。
3. TCP 状态转换
三次握手状态:
-
SYN_SENT:客户端发送SYN包后进入该状态。 -
SYN_RECEIVED:服务器收到SYN包并发送SYN + ACK包后进入该状态。 -
ESTABLISHED:连接建立完成,双方进入该状态。
四次挥手状态:
-
FIN_WAIT_1:发送FIN包后进入该状态。 -
FIN_WAIT_2:收到对方的ACK包后进入该状态。 -
CLOSE_WAIT:收到对方的FIN包后进入该状态。 -
LAST_ACK:发送FIN包后进入该状态。 -
TIME_WAIT:发送最后的ACK包后进入该状态,等待 2MSL(Maximum Segment Lifetime)后关闭连接。

4. 常见问题
为什么 TIME_WAIT 状态需要等待 2MSL?
-
确保最后的
ACK包到达:如果最后的ACK包丢失,对方会重传FIN包,TIME_WAIT状态可以重新发送ACK包。 -
防止旧连接的重复数据包:等待 2MSL 可以确保网络中所有旧连接的包都消失,避免与新连接混淆。
如果服务器大量处于 CLOSE_WAIT 状态怎么办?
-
检查应用程序:可能是应用程序未正确关闭连接,导致
CLOSE_WAIT状态堆积。 -
调整超时时间:可以通过调整
net.netfilter.nf_conntrack_tcp_timeout_close_wait参数优化。
总结
-
三次握手:用于建立 TCP 连接,确保双方都能收发数据。
-
四次挥手:用于关闭 TCP 连接,确保双方都完成数据传输并安全关闭。
-
状态转换:TCP 连接在不同状态下转换,确保连接的可靠性和完整性。
