TIME WAIT

主动关闭方在收到被关闭方的FIN后会处于并长期(2个MSL时间,建议值是2min)的状态,大约是1-4分钟。然后由操作系统回头连接并将TCP连接设为CLOSED初始状态。

CLOSE WAIT

是被动关闭连接形成的,被动端收到主动端的FIN时候,发送ACK确认,并进入CLOSE_WAIT的状态,如果不指定close()方法,那么就不能从 CLOSE_WAIT 迁移到LAST_ACK,则系统中会有很多的CLOSE_WAIT状态的链接。

FAQ

  1. 为什么建立连接协议是三次握手,而关闭连接却是四次握手呢?
    因为建立连接的时候,对方可以把ACK和SYN放在一个报文里发送。
  2. 为什么 TIME_WAIT 状态还需要等 2MSL 后才能返回到 CLOSED 状态?
    因为不确定最后发送的 ACK 被对方收到了,所以先进入 TIME_WAIT 状态,作用是用来重发可能丢失的 ACK 报文。

如何排查

可以通过 netstat -n 结合 awk 打印这两个数值

意义

如果这两种状态过多,将会出现较高的负载,导致新的连接无法建立,或者导致socket资源耗尽。可以修改内核 TIME_WAIT 的值一定程度解决。

三次握手

  1. 客户端 A 发送 SYN 包(SYN=j)到服务器 B,并进入SYN_SEND 状态,等待服务器 B 确认。
  2. 服务器 B 收到 SYN 包,必须确认客户 A 的 SYN(ACK=j+1),同时自己也发送一个 SYN 包(SYN=k),即 ACK+SYN 包,此时服务器 B 进入SYN_RECV 状态。
  3. 客户端 A 收到服务器 B 的 SYN+ACK 包,向服务器 B 发送确认包 ACK(ACK=k+1)。此包发送完毕,客户端 A 和服务器 B 进入 ESTABLISHED 状态,完成三次握手。

四次挥手

  1. 客户端 A 发送一个 FIN,用来关闭客户 A 到服务器 B 的数据传送。

  2. 服务器 B 收到这个 FIN,它发回一个 ACK,确认序号为收到的序号加1。和 SYN 一样,一个 FIN 将占用一个序号。

  3. 服务器 B 关闭与客户端 A 的连接,发送一个 FIN 给客户端 A。

  4. 客户端 A 发回 ACK 报文确认,并将确认序号设置为收到序号加1。

因为要建立可靠的连接,以及全双工。