TCP/IP之TIME_WAIT和CLOSE_WAIT
TCP/IP四次挥手
要了解 TIME_WAIT 和 CLOSE_WAIT 就需要了解一下TCP/IP的四次挥手,因为这两个状态发生在四次挥手的过程
client和server端
在这里我们这么定义client 和 server 端:
- client: 主动发起关闭的一方
- server: 被动接收关闭的一方
四次挥手过程
- 首先 client 和 server 都处理 ESTABLISHED 状态
- client 发送 FIN, 同时发送
seq=x
(x随机数), client 进入 SYNC_SENT 状态,发送成功后进入 FIN_WAIT_1 状态 - server 接收后,发送
ACK=1,ack=x+1
给 client, 然后 server 进入 CLOSE_WAIT (通知应用层关闭) 状态 - client 接收到 ACK 后,进入 FIN_WAIT_2 状态,此时
- server 端结束 CLOSE_WAIT 状态, 然后发送 FIN 给 client, 同时发送
seq=y
, 进入 LAST_ACK 状态 - client 接收后,发送
ACK=1,ack=y+1
给 server,此时 client 就进入 TIME_WAIT 状态,此时TCP连接还没有释放,必须经过2∗MSL
(最长报文段寿命) - server 接收到 cliet 端的 ACK 后,就进入 CLOSED 状态,此时就断开了TCP连接
注意,其中大小写ack是有区别的:
- ACK:
Acknowledgement
是标识位,[ACK] or [SYC] or [FIN]
- ack:
Acknowledgement Number
, 是确认序列号。收到seq=x 的数据包后,回复ack=x+1
的确认
CLOSE_WAIT
CLOSE_WATI 存在的意义在于当 server 端接收到 client FIN消息且发送 ACK 给 client 端后,需要关闭应用层的各项活动
TIME_WAIT
那么为什么设计 TIME_WAIT 呢? 而且是 2*MSL
?
为什么设计存在 TIME_WAIT ?
原因:
- 保证 server 端能够接收 LAST_ACK
- 保证同次连接的延迟数据包消失
保证 server 端能够接收 LAST_ACK:
假定 client 端没有这个TIME_WAIT状态,当发送完 ACK 后就直接进入 CLOSED 状态,如果由于某种原因,server端没有接收到来自client 端的 LAST_ACK, 这时候,server 端会重新发送 FIN 等待client 端的重新 ACK, 但是此时的 client 已经是 CLOSE 状态了,即和原来不是属于同一次连接,所以就不能进行client 端的ACK。 如果存在 TIME_WAIT 状态, client接收到 server 端重新发送的 FIN 消息,就会再次进行 ACK 确认,完成挥手操作
保证同次连接的延迟数据包消失
假定 client 直接进入 CLOSED 状态,之后客户端又重新发送连接请求,那么有可能使用和之前关闭的端口一样。在网络链路上就避免不了存在上次连接中延迟的数据包,那么TCP就会误认为是属于新创建的连接的中的数据包,造成新旧数据包的混淆。所以 TIME_WAIT 为
2*MSL
时间,保证属于本次连接的数据包从网络中消失