天天看点

一个 CLOSE_WAIT 问题 - TCP 三次握手原理(备忘)

CLOSE_WAIT 问题

原因很简单:TCP 四次挥手问题,发起于 FIN 指令

具体细节,请自行百度

需要注意的是,CLOSE_WAIT 只存在于 socket 连接已经连接成功后

错误的文章诱导

点名批评下 : http://blog.huoding.com/2016/01/19/488

具体摘录如下:

一个 CLOSE_WAIT 问题 - TCP 三次握手原理(备忘)

了解服务器端成功建立连接过程中的行为

参考文章:

  • https://blog.csdn.net/alitech2017/article/details/80922902
  • http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html

上面 2 篇文章把服务器端连接过程中的问题,以及 backlog 工作原理见得很清楚了

这里再简单复述下过程,见图:

一个 CLOSE_WAIT 问题 - TCP 三次握手原理(备忘)
  1. 客户端(53302) 发送 SYN 指令,请求建立连接
  2. 服务器端(999) 发送 SYN-ACK 指令,应答(socket 到 sync queue)
  3. 客户端(53302) 发送 ACK 指令,并认为自己已经连接完成
  4. 服务器端(999) 收到 ACK 指令后,发现 accept queue 满,则丢弃 ACK 包
  5. 服务器端(999) 重复

    BackOff (退避算法)

    ,发送 SYN-ACK 指令
  6. 服务器端(999) 一直没有收到客户端 ACK 指令的话,最终会发送 RST 指令,关闭连接

上述流程中,服务器端做第 5 部时,客户端在做下面事情:

  • 客户端(53302) 会开始发送数据 PSH-ACK (因为客户端认为连接已经建立成功)
  • 然后因为收不到服务器端(999) 的 ACK 包,重复

    BackOff (退避算法)

    ,发送数据 PSH-ACK

上述图中没有的另外一种情况,客户端认为连接已经建立成功后,不发数据,然后被服务器端(999)最终会发送 RST 指令,关闭连接

因此, 服务器端:

  • 要么收到客户端发送的 ACK 指令,完成三次握手。 accpet() 函数返回 socket 对象
  • 要么发送 RST 指令结束连接

socket 状态图

下图摘自网络文章,主要说明下: CLOSE_WAIT 只可能出现在 ESTABLISHED 状态后面;且只有收到 FIN 指令才转移

一个 CLOSE_WAIT 问题 - TCP 三次握手原理(备忘)

结论

  1. TCP 连接建立过程中,服务器端只会发送 RST 指令重置连接
  2. backlog 值只可能让大量连接无法连接上服务器
  3. CLOSE_WAIT 只可能出现在 ESTABLISHED 状态后面;且只有收到 FIN 指令才转移

其他

文中提到

BackOff (退避算法)

,这个可能不是 TCP 中的专有名词,总之表达一个意思, 下次重复发送指令的时间会变长

继续阅读