还是用一下上一篇文章画的图
TCP 的 11 个状态,每一个状态都缺一不可,自然 TIME_WAIT 状态被赋予的意义也是相当重要,咱们直接结论先行
上文我们提到 tcp 中,主动关闭的一边会进入 TIME_WAIT 状态,
另外 Tcp 中的有 TIME_WAIT 状态,主要是有如下 2 个原因:
- 为了防止被动关闭一方的延迟数据被其他连接窃取
- 为了防止被动关闭的一方,没有收到最后的一个 ACK 包
如何理解呢?
为了防止被动关闭一方的延迟数据被其他连接窃取
对于第一个
咱们一个一个的来详细解释一下,还是上面这个图,咱们人为的加一点异常的情况
咱们在 tcp 连接中,客户端先发起关闭,那么 TIME_WAIT 状态就在客户端这边,如下:
这是一个正常的客户端和服务端通信的基本过程,那么,如果在 client 和 server 建立连接后,server 端向 client 端发发送的数据,在网络环境中有延迟,短时间,没有顺利的达到 client 端的时候,就会出现如下情况
如上图
- 我们人为的画了一个会出现在现实工作中的问题,当 client 和 server 正常连接,server 给 client 发的 seq=100 的包,由于网络拥堵等原因,留在了网络环境中
- client 首先发起关闭连接,如果这个时候,没有 TIME_WAIT 状态,或者咱们人为的将 TIME_WAIT 的值设小,就会出现 seq=100 这个包不能正常的被 client 收到,因为 client 已经是 CLOSED 状态了
- 这个时候,和 client 占用同一端口的程序 client 路人启动程序并和 server 成功建立连接之后,刚才的 seq=100 的包才到目的地址,这个时候 client 路人并不期望收到这个 seq=100 的消息,那么这对 client 路人来说,这就是一个异常问题了
如果咱们的 TIME_WAIT 状态存在,或者是正常保持 2MSL 的时间,就不会出现这个情况 ,1 个 MSL 是报文在网络环境中的最大存活时间,对于上面这个例子, client 现在那就还是 TIME_WAIT 状态, client 路人使用 client 的端口,是无法启动的,且 2MSL 的时间 seq=100 是完全可以达到 client 的
那是否会有人问,为什么 client 程序还在的时候,就不能启动 client 路人程序呢?
对于这个,咱们就需要知道 TCP 的一条连接,是由四元组组成的
- 源地址
- 源端⼝
- ⽬的地址
- ⽬的端⼝
此处我们知道,client 和 client 路人,源地址,目的地址,目的端口,都是一样的,那么此时如果源端口还是一样的话,那么是没有办法 2 个 client 都能正常启动的,其中一个正常启动了,那么另外一个就会报地址已经被使用
为了防止被动关闭的一方,没有收到最后的一个 ACK 包
再来看第二点
其实上面我们隐约已经说到了这一点,只不过不是 ack 包,再使用一下上面的图,我们人为的弄一个异常情况
如上图,当我们的 TIME_WAIT 状态不存在,或者设置的时间较小的时候,就可能会发生被动关闭的一方,收不到最后的一个 ack 包的情况
- 一条 tcp 连接的四元组现在我们知道是啥意思了,那么,当上述 server 对应的连接还未是 CLOSED 状态的时候,server 是认为当前连接还是存在的
- 但是 client 自身已经是 CLOSED 状态了,所以对于 client 路人来说,我当前的连接是有效的,因此我去给 server 发握手包
- 可是万万没有想到,server 拒绝我的连接,client 路人就很蒙圈
此时,如果 TIME_WAIT 状态存在,并且等待的时间是 2MSL ,那么哪怕最后一个 ack 包丢失了,server 端也可以重新发送一个 FIN 包给到 client ,再等待一个新的 ack 包
这样,2 MSL 之后,client 和 server 端,对于这一条连接,都是正常关闭的
所以,为什么需要 TIME_WAIT 状态,心里有点数了不
感谢阅读,欢迎交流,点个赞,关注一波 再走吧
欢迎点赞,关注,收藏
朋友们,你的支持和鼓励,是我坚持分享,提高质量的动力
好了,本次就到这里
技术是开放的,我们的心态,更应是开放的。拥抱变化,向阳而生,努力向前行。
我是阿兵云原生,欢迎点赞关注收藏,下次见~