TCP的三次握手(建立连接)
TCP 是面向连接的协议,通信前需先建立可靠连接。三次握手的目的是同步双方的初始序列号(ISN),并确认双方的收发能力正常。
握手过程:
-
第一次握手(SYN):
-
客户端发送
SYN=1
(同步标志位)和随机序列号seq=x
。 -
状态:客户端进入
SYN_SENT
。
-
-
第二次握手(SYN+ACK):
-
服务器收到
SYN
后,回复SYN=1
、ACK=1
(确认标志位),并发送自己的序列号seq=y
和确认号ack=x+1
。 -
状态:服务器进入
SYN_RCVD
。
-
-
第三次握手(ACK):
-
客户端收到
SYN+ACK
后,回复ACK=1
,确认号ack=y+1
。 -
状态:双方进入
ESTABLISHED
(连接建立成功)。
-
为什么需要三次?
-
两次握手的风险:若失效的客户端
SYN
请求延迟到达服务器,服务器会误认为新连接,导致资源浪费。 -
三次握手确保双向通信可靠:
-
客户端确认:自己能发、能收。
-
服务器确认:自己能收、能发。
-
TCP的四次挥手(断开连接)
TCP 是全双工的,双方需分别关闭自己的数据通道。四次挥手的目的是安全释放连接资源。
挥手过程:
-
第一次挥手(FIN):
-
主动关闭方(如客户端)发送
FIN=1
和序列号seq=u
。 -
状态:客户端进入
FIN_WAIT_1
。
-
-
第二次挥手(ACK):
-
被动关闭方(如服务器)收到
FIN
后,回复ACK=1
和确认号ack=u+1
。 -
状态:服务器进入
CLOSE_WAIT
,客户端收到后进入FIN_WAIT_2
。 -
此时:服务器可能仍有数据要发送(半关闭状态)。
-
-
第三次挥手(FIN):
-
服务器完成数据发送后,发送
FIN=1
和序列号seq=w
。 -
状态:服务器进入
LAST_ACK
。
-
-
第四次挥手(ACK):
-
客户端收到
FIN
后,回复ACK=1
和确认号ack=w+1
。 -
状态:客户端进入
TIME_WAIT
(等待2MSL
后关闭),服务器直接关闭。
-
为什么需要四次?
-
TCP 是全双工的,需分别关闭两个方向的数据流。
-
第二次挥手(
ACK
)和第三次挥手(FIN
)不能合并:-
服务器可能在
CLOSE_WAIT
状态继续发送剩余数据。
-
关键问题解析
1. 为什么TIME_WAIT状态要等待2MSL?
-
MSL(Maximum Segment Lifetime):报文最大生存时间(通常为30秒~2分钟)。
-
目的:
-
确保最后一个
ACK
能到达服务器(若丢失,服务器会重发FIN
)。 -
让网络中残留的旧报文失效,避免影响新连接。
-
2. 握手可以四次吗?
-
理论上可以(如同时发送
SYN
),但实际优化为三次。
3. 挥手可以三次吗?
-
可以!如果服务器在第二次挥手时没有数据要发送,会合并
ACK
和FIN
(变为三次)。
示意图
三次握手
Client Server|-------- SYN (seq=x) ----------->| |<---- SYN+ACK (seq=y, ack=x+1) --| |-------- ACK (ack=y+1) -------->|
四次挥手
Client Server|-------- FIN (seq=u) ----------->| |<------- ACK (ack=u+1) ----------| |<------- FIN (seq=w) ------------| |-------- ACK (ack=w+1) -------->|
实际应用
-
握手失败:可能是防火墙阻止、端口未开放。
-
大量TIME_WAIT:高并发短连接时需优化(如调整
tcp_tw_reuse
参数)。 -
半连接队列:服务器在
SYN_RCVD
状态时存储未完成的握手请求(需防SYN洪水攻击)。
理解握手和挥手是排查网络问题(如连接超时、端口占用)的基础!