TCP四次挥手
TCP拆除连接需要发送四个包成为四次挥手,客户端和服务端均可发起挥手动作(以下假设客户端发起挥手动作)
刚开始双方处于ESTABLISHED
状态
- 第一次挥手:客户端要断开了,向服务器发送
FIN
报文,客户端变成了FIN-WAIT-1
状态。此时客户端同时也变成了half-close(半关闭)
状态,即无法向服务端发送报文,只能接收。 - 第二次挥手:服务端接收后向客户端确认,变成了
CLOSE-WAIT
状态,客户端接收到了服务端的确认,变成了FIN-WAIT2
状态 - 第三次挥手:服务端向客户端发送
FIN
,自己进入LAST-ACK
状态 - 第四次挥手:客户端收到了服务端发来的
FIN
后,自己变成了TIME-WAIT
状态,然后发送ACK
给服务端 - 注意:这个时候,客户端需要等待足够长的时间,具体来说是2个MSL(Maximum Segment Lifetime,报文最大生存时间),在这段时间内如果客户端没有收到服务端的重发请求,那么表示ACK成功到达,挥手结束,否则客户端重发ACK
等待2MSL的意义
如果不等待,客户端直接跑路,当服务端还有很多数据包要给客户端发,且还在路上的时候,若客户端的端口此时刚好被新的应用占用,那么接收到了无用数据包,造成数据混乱。所以最保险的做法是等待服务器发来的数据包都失效时再启动新的应用
那么为什么要等待2MSL,而不是1MSL
- 1个MSL确保四次挥手中主动关闭放最后的ACK报文能到达对端
- 1个MSL确保对端没有收到ACK重传的FIN报文可以到达。
为什么是四次挥手而不是三次
因为服务端在接收到FIN
,往往不会立即返回FIN
,必须等到服务端所有的报文都发送完毕了,才能发FIN
。因此先发一个ACK
表示已经收到客户端的FIN
, 延迟一段时间才发FIN
。就造成了四次挥手。
三次挥手会造成什么问题
- 服务端将
ACK
和FIN
的发送合并为一次挥手,这个时候长时间的延迟可能会导致客户端误以为FIN
没有到达客户端,从而让客户端不断的重发FIN