关于TCP三次握手和四次挥手的思考
握手
三次握手流程
第一步:客户端发送 SYN(同步请求)
报文内容:
标志位:
SYN=1
(请求建立连接)序列号(Sequence Number):
seq=x
(随机生成的初始值)
客户端状态:
SYN_SENT
作用:客户端向服务器声明自己的初始序列号(
x
),请求建立连接。
第二步:服务器回复 SYN-ACK(同步确认)
报文内容:
标志位:
SYN=1
(接受连接请求) +ACK=1
(确认客户端的 SYN)序列号:
seq=y
(服务器随机生成的初始值)确认号(Acknowledgment Number):
ack=x+1
(期望收到客户端下一个报文的序列号)
服务器状态:
SYN_RECEIVED
作用:
确认客户端的
SYN
(通过ack=x+1
)声明服务器的初始序列号(
y
)
第三步:客户端发送 ACK(最终确认)
报文内容:
标志位:
ACK=1
序列号:
seq=x+1
(客户端初始序列号 +1)确认号:
ack=y+1
(期望收到服务器下一个报文的序列号)
双方状态:
ESTABLISHED
作用:
确认服务器的
SYN
(通过ack=y+1
)连接正式建立,双方可开始传输数据。
关键机制解析
序列号(Sequence Number):
初始值为随机数(防止历史报文干扰)
后续数据按序列号顺序传输,确保可靠性。
为什么需要三次握手?
防止已失效的连接请求:若只有两次握手,网络中滞留的旧
SYN
报文可能被服务器误认为新请求,导致资源浪费。双向确认:确保双方均确认对方的发送和接收能力正常。
抓包示例(Wireshark视角)
No. Time Source Destination Protocol Info
1 0.000000 Client_IP Server_IP TCP SYN (seq=100)
2 0.000042 Server_IP Client_IP TCP SYN, ACK (seq=200, ack=101)
3 0.000078 Client_IP Server_IP TCP ACK (seq=101, ack=201)
观察要点:
三次交互的
SYN
和ACK
标志位变化序列号(
seq
)和确认号(ack
)的递增逻辑时间间隔(RTT,反映网络延迟)
常见问题与故障场景
握手失败原因:
SYN未到达:防火墙拦截、网络不通
SYN-ACK未返回:服务器未监听端口、负载过高
ACK丢失:客户端未正确处理 SYN-ACK
SYN洪泛攻击(SYN Flood):
攻击者伪造大量
SYN
请求但不回复ACK
,耗尽服务器资源。防御:SYN Cookie 技术、限制半开连接数。
扩展思考
四次挥手(连接终止):通过
FIN
和ACK
报文分四次交互,确保数据完整传输。TCP Fast Open(TFO):优化握手流程,允许在首次 SYN 中携带数据(需协议支持)。
掌握三次握手原理后,可通过 Wireshark 抓包验证理论,并进一步分析网络延迟、连接重置(RST)等故障。
挥手
以下是 TCP 四次挥手(Four-way Handdrawal) 的详细解析,这是 TCP 连接终止的标准过程,确保双方数据完整传输并安全释放资源:
四次挥手流程
第一步:主动关闭方发送 FIN(终止请求)
报文内容:
标志位:
FIN=1
(请求终止连接)序列号(Sequence Number):
seq=u
(当前已传输数据的最后一个字节序号 +1)
主动方状态:从
ESTABLISHED
变为FIN_WAIT_1
作用:通知对方“我已无数据发送,请求关闭连接”(但仍可接收数据)。
第二步:被动关闭方回复 ACK(确认终止请求)
报文内容:
标志位:
ACK=1
确认号(Acknowledgment Number):
ack=u+1
(确认 FIN 报文)序列号:
seq=v
(被动方当前数据序号)
被动方状态:从
ESTABLISHED
变为CLOSE_WAIT
作用:
确认收到 FIN 请求(
ack=u+1
)被动方可能仍有数据待发送(此时进入半关闭状态,只能发送不能接收)。
第三步:被动关闭方发送 FIN(最终关闭请求)
报文内容:
标志位:
FIN=1
+ACK=1
序列号:
seq=w
(若第二步后被动方未发送新数据,则w=v
)确认号:
ack=u+1
(与第二步一致)
被动方状态:从
CLOSE_WAIT
变为LAST_ACK
触发条件:被动方数据全部发送完成后,主动发起 FIN 请求。
第四步:主动关闭方回复 ACK(最终确认)
报文内容:
标志位:
ACK=1
序列号:
seq=u+1
(第一步 FIN 报文的序列号 +1)确认号:
ack=w+1
(确认被动方的 FIN 报文)
主动方状态:从
FIN_WAIT_2
进入TIME_WAIT
(等待 2MSL 后关闭)作用:
确保被动方收到最终 ACK(若丢失,被动方会重传 FIN)
等待处理网络中残留的旧报文(防止干扰新连接)。
关键机制解析
为什么需要四次挥手?
TCP 是全双工协议,双方需独立关闭各自的发送通道:
主动方发 FIN 表示“我不再发送数据”
被动方发 FIN 表示“我也停止发送数据”
ACK 和 FIN 不能合并发送(被动方可能需处理遗留数据)。
TIME_WAIT 状态的意义:
等待时间:2MSL(Maximum Segment Lifetime,报文最大生存时间,通常 60~120秒)
核心作用:
确保最后一个 ACK 到达被动方(若丢失,被动方会重传 FIN)
清除网络中滞留的旧报文(避免与新连接冲突)。
半关闭状态(Half-Close):
在第二步后,被动方处于
CLOSE_WAIT
状态,仍可向主动方发送数据。典型场景:服务器通知客户端“数据已传完,准备关闭”。
抓包示例(Wireshark视角)
No. Time Source Destination Protocol Info
1 0.000000 Client_IP Server_IP TCP FIN, ACK (seq=1000, ack=5000)
2 0.000042 Server_IP Client_IP TCP ACK (seq=5000, ack=1001)
3 5.000120 Server_IP Client_IP TCP FIN, ACK (seq=5000, ack=1001)
4 5.000150 Client_IP Server_IP TCP ACK (seq=1001, ack=5001)
观察要点:
前两次交互关闭主动方通道,后两次关闭被动方通道。
序列号和确认号的递增逻辑(
ack=seq+1
)。时间戳差异(第三步可能有延迟,因被动方需处理数据)。
常见问题与故障场景
挥手异常情况:
FIN 丢失:主动方重传 FIN(超时机制)。
LAST_ACK 状态卡死:若第四步 ACK 丢失,被动方持续重传 FIN。
大量 TIME_WAIT 连接:高频短连接导致端口耗尽(优化:调整
SO_REUSEADDR
参数)。
为什么有时看到三次挥手?
被动方的 ACK 和 FIN 可能合并发送(当被动方无数据待发时),但严格遵循 TCP 标准应为四次。
恶意 FIN 攻击:
攻击者伪造 FIN 报文强制关闭连接。
防御:校验 SEQ/ACK 号合法性,或启用 TCP 身份验证(如 TCP-AO)。
💡注意:很多人会参考网上的博客去优化服务器参数,但请慎用
net.ipv4.tcp_tw_recycle = 1
,可能导致 NAT 问题。
扩展思考
同时关闭(Simultaneous Close):双方同时发送 FIN,进入
CLOSING
状态,最终通过 ACK 确认。RST 报文强制终止:通过
RST=1
直接重置连接(不经历四次挥手,用于异常场景)。
掌握四次挥手机制后,可有效诊断以下问题:
服务器出现大量
CLOSE_WAIT
连接(通常因应用未正确调用close()
)客户端
TIME_WAIT
积累导致无法建立新连接防火墙误杀 FIN/ACK 报文导致连接无法正常关闭