CLOSE_WAIT 问题
原因很简单:TCP 四次挥手问题,发起于 FIN 指令
具体细节,请自行百度
需要注意的是,CLOSE_WAIT 只存在于 socket 连接已经连接成功后
错误的文章诱导
点名批评下 : http://blog.huoding.com/2016/01/19/488
具体摘录如下:
了解服务器端成功建立连接过程中的行为
参考文章:
- https://blog.csdn.net/alitech2017/article/details/80922902
- http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html
上面 2 篇文章把服务器端连接过程中的问题,以及 backlog 工作原理见得很清楚了
这里再简单复述下过程,见图:
- 客户端(53302) 发送 SYN 指令,请求建立连接
- 服务器端(999) 发送 SYN-ACK 指令,应答(socket 到 sync queue)
- 客户端(53302) 发送 ACK 指令,并认为自己已经连接完成
- 服务器端(999) 收到 ACK 指令后,发现 accept queue 满,则丢弃 ACK 包
- 服务器端(999) 重复
,发送 SYN-ACK 指令BackOff (退避算法)
- 服务器端(999) 一直没有收到客户端 ACK 指令的话,最终会发送 RST 指令,关闭连接
上述流程中,服务器端做第 5 部时,客户端在做下面事情:
- 客户端(53302) 会开始发送数据 PSH-ACK (因为客户端认为连接已经建立成功)
- 然后因为收不到服务器端(999) 的 ACK 包,重复
,发送数据 PSH-ACKBackOff (退避算法)
上述图中没有的另外一种情况,客户端认为连接已经建立成功后,不发数据,然后被服务器端(999)最终会发送 RST 指令,关闭连接
因此, 服务器端:
- 要么收到客户端发送的 ACK 指令,完成三次握手。 accpet() 函数返回 socket 对象
- 要么发送 RST 指令结束连接
socket 状态图
下图摘自网络文章,主要说明下: CLOSE_WAIT 只可能出现在 ESTABLISHED 状态后面;且只有收到 FIN 指令才转移
结论
- TCP 连接建立过程中,服务器端只会发送 RST 指令重置连接
- backlog 值只可能让大量连接无法连接上服务器
- CLOSE_WAIT 只可能出现在 ESTABLISHED 状态后面;且只有收到 FIN 指令才转移
其他
文中提到
BackOff (退避算法)
,这个可能不是 TCP 中的专有名词,总之表达一个意思, 下次重复发送指令的时间会变长