TCP的TIME_WAIT和CLOSE_WAIT

1.四次挥手服务端和客户端的状态:

  • 主动关闭连接的一方,调用 close ();协议层发送 FIN 包;
  • 被动关闭的一方收到 FIN 包后,协议层回复 ACK;然后被动关闭的一方,进入 CLOSE_WAIT 状态,主动关闭的一方等待对方关闭,则进入 FIN_WAIT_2 状态;此时,主动关闭的一方等待被动关闭一方的应用程序,调用 close 操作;
  • 被动关闭的一方在完成所有数据发送后,调用 close () 操作;此时,协议层发送 FIN 包给主动关闭的一方,等待对方的 ACK,被动关闭的一方进入 LAST_ACK 状态;
  • 主动关闭的一方收到 FIN 包,协议层回复 ACK;此时,主动关闭连接的一方,进入 TIME_WAIT 状态;而被动关闭的一方,进入 CLOSED 状态;
  • 等待 2MSL 时间,主动关闭的一方,结束 TIME_WAIT,进入 CLOSED 状态;

在这里插入图片描述

2.总结上面的过程,得出一次 socket 关闭操作:

  • 主动关闭连接的一方 – 也就是主动调用 socket 的 close 操作的一方,最终会进入 TIME_WAIT 状态;
  • 被动关闭连接的一方,有一个中间状态,即 CLOSE_WAIT,因为协议层在等待上层的应用程序,主动调用 close 操作后才主动关闭这条连接;
  • TIME_WAIT 会默认等待 2MSL(2 倍的max segment lifetime) 时间后,才最终进入 CLOSED 状态;
  • 在一个连接没有进入 CLOSED 状态之前,这个连接是不能被重用的!

3.TIME_WAIT 并不可怕,CLOSE_WAIT 才可怕,因为 CLOSE_WAIT 很多,表示说:

  • 要么是你的应用程序写的有问题,没有合适的关闭 socket
  • 要么是说,你的服务器 CPU 处理不过来(CPU 太忙)或者你的应用程序一直睡眠到其它地方 (锁,或者文件 I/O 等等),你的应用程序获得不到合适的调度时间,造成你的程序没法真正的执行 close 操作

4.TIME_WAIT 有什么用?

  • 防止前一个连接上延迟的数据包或者丢失重传的数据包,被后面复用的连接错误的接收
  • 确保连接方能在时间范围内,关闭自己的连接

5.为什么 TIME_WAIT 状态 停留 2MSL(max segment lifetime)时间?

  • 为了防止上次连接的报文数据影响到下次的连接,有充分的的时间处理上次连接的报文信息。

  • 客户端最后发的 ACK 可能会丢失,此时服务器端会重新发送 FIN,若此时客户端处于 closed,会响应 rst (rst 段标识复位,用来异常的关闭连接) 而不是 ACK。因此客户端是 TIME_WAIT 状态,不是 closed。

6.什么原因造成出现大量CLOSE_WAIT?

  • 出现大量 close_wait 的现象主要原因是某种情况下对方关闭了 socket 链接,但是我方忙与读或者写,没有关闭连接。

7.什么原因造成大量 TIME_WAIT

  • 在高并发短连接的 TCP 服务器上,当服务器处理完请求后立刻主动正常关闭连接。这个场景下会出现大量 socket 处于 TIME_WAIT 状态。如果客户端的并发量持续很高,此时部分客户端就会显示连接不上。

8.如何处理大量CLOSE_WAIT?

  • 给每一个 socket 设置一个时间戳 last_update,每接收或者是发送成功数据,就用当前时间更新这个时间戳。定期检查所有的时间戳,如果时间戳与当前时间差值超过一定的阈值,就关闭这个 socket。
  • 使用一个 Heart-Beat 线程,定期向 socket 发送指定格式的心跳数据包,如果接收到对方的 RST 报文,说明对方已经关闭了 socket,那么我们也关闭这个 socket。

【Java 面试那点事】

这里致力于分享 Java 面试路上的各种知识,无论是技术还是经验,你需要的这里都有!

这里可以让你【快速了解 Java 相关知识】,并且【短时间在面试方面有跨越式提升】

面试路上,你不孤单!
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章