先了解一下四次挥手过程
在挥⼿之前,客户端和服务器都处于
ESTABLISHED
状态
1.
第⼀次挥⼿:假设客户端打算关闭连接,发送⼀个
TCP
⾸部
FIN
被置
1
的
FIN
报⽂给服务端
,
此时客户端处于 FIN_WAIT1 状态
2.
第⼆次挥⼿:服务端收到以后,向客户端发送
ACK
应答报⽂,且把客户端的序列号值
+1
作为
ACK
报⽂的序列号值,表明已经收到客户端的报⽂了,此时服务端处于 CLOSE_WAIT
状态
3.
第三次挥⼿:等待服务端处理完数据后,向客户端发送
FIN
报⽂。此时服务端处于
LAST_ACK
的状态
4.
第四次挥⼿:客户端接收到
FIN
报⽂后回⼀个
ACK
应答报⽂,之后客户端处于
TIME_WAIT
状态
5.
服务器收到
ACK
报⽂后,进⼊
CLOSE
状态,服务器完成连接关闭。
6.
客户端在经过
2MSL
⼀段时间后,⾃动进⼊
CLOSE
状态,客户端也完成连接的关闭
为什么需要 TIME_WAIT 状态
主动发起关闭连接的⼀⽅,才会有
TIME-WAIT
状态。
需要
TIME-WAIT
状态,主要是两个原因:
1. 防止历史连接中的数据,被后面相同四元组的连接错误的接收;
如果⽹络出现拥塞或延迟,数据包可能会在⽹络中滞留⼀段时间,甚⾄超过了原始连接关闭的时间。如果没有 TIME_WAIT 状态,客户端直接进⼊到CLOSE
状态,这些滞留的数据包可能会被传递给新连接,导致新连接的数据 被旧连接的数据⼲扰。 经过 2MSL
这个时间,
⾜以让两个⽅向上的数据包都被丢弃,使得原来连接的数据包在⽹络中都⾃然消失,再出现
的数据包⼀定都是新建⽴连接所产⽣的。
2. 保证「被动关闭连接」的⼀⽅能被正确的关闭,即保证最后的 ACK 能让被动关闭⽅接收,从⽽帮助其正常关闭
如果最后的⼀次ACK
报⽂丢失(第四次挥⼿),客户端没有
TIME_WAIT
状态,直接进⼊
ClOSE
,服务端⼀直在等待 ACK状态,⼀直没有等到,就会重发
FIN
报⽂,⽽客户端已经进⼊到关闭状态,在收到服务端重传的
FIN
报⽂后, 就会回 RST
报⽂
,
服务端收到这个
RST
并将其解释为⼀个错误
,
为了防⽌这种情况出现,客户端必须等待⾜够⻓的时间,确保服务端能够收到 ACK
,如果服务端没有收到
ACK
,那么就会触发
TCP
重传机制,服务端会重新发送⼀个FIN,这样⼀去⼀来刚好两个
MSL
的时间。
如果 TIME-WAIT 等待⾜够⻓的情况就会遇到两种情况:
1.
服务端正常收到四次挥⼿的最后⼀个
ACK
报⽂,则服务端正常关闭连接。
2.
服务端没有收到四次挥⼿的最后⼀个
ACK
报⽂时,则会重发
FIN
关闭连接报⽂并等待新的
ACK
报⽂。
为什么 TIME_WAIT 等待的时间是 2MSL
1. MSL
是
Maximum Segment Lifetime
,报⽂最⼤⽣存时间,它是任何报⽂在⽹络上存在的最⻓时间,超过这 个时间报⽂将被丢弃。
2.
等待
MSL
两倍:⽹络中可能存在发送⽅的数据包,当这些发送⽅的数据包被接收⽅处理后⼜会向对⽅发送响应,所以⼀来⼀回需要等待 2
倍的时间。
3. 1
个
MSL
确保四次挥⼿中主动关闭⽅最后的
ACK
报⽂最终能达到对端;
1
个
MSL
确保对端没有收到
ACK
重传的 FIN
报⽂可以到达。
4. 2MSL
的时间是从客户端接收到
FIN
后发送
ACK
开始计时的。如果在
TIME-WAIT
时间内,因为客户端的
ACK没有传输到服务端,客户端⼜接收到了服务端重发的 FIN
报⽂,那么
2MSL
时间将重新计时。