◆急!端口能telnet通,但远程桌面连接一直处理CLOSE_WAIT状态。

◆急!端口能telnet通,但远程桌面连接一直处理CLOSE_WAIT状态。,第1张

我们是几户人家共享一条长城宽带上网的,最近出现个奇怪的问题。默认的远程连接端口3389可以正常连接出去,但是有一个客户的远程端口是17909 却一直连接不了(原来可以最近几天才不行,到朋友家也可以正常远程),用netstat发现一直处于CLOSE_WAIT状态如:TCP 22223:17909 CLOSE_WAIT (号同为ip地址)我用telnet测试 telnet 22223 17909 也能正常连接。到一个朋友家的电脑却可以正常远程连接22223:17909 ,而在我家里原来也能一直正常使用的,就是最近几天才不行。分析:1能telnet通这个端口应该说明路由器没有屏蔽掉这个端口。2能远程连接别的机子的3389端口说明远程桌面软件没有被屏蔽。3在朋友的电脑上能正常远程连接22223 17909 说明机房的网络是正常的。

CLOSE_WAIT 表示已经关闭,处于侦听状态的网络连接(一有需要会立即连接);
补充:
这是查看本机网络连接状态的命令,
标记为ESTALISHED 的,就是已经建立的网络连接;
TIME-WAIT 表示等待连接的网络连接;
CLOSE_WAIT 表示已经关闭,处于侦听状态的网络连接(一有需要会立即连接);
TCP UDP表示网络协议类型;

<div style="text-align: right">LexusLee</div>

最近踩到一个 "Socket 连接持续处于 Fin_Wait2 和 Close_Wait 状态无法关闭" 的坑中。起因是在维护大量连接时调用 socketclose() 时,看到部分连接并没有正常关闭,而是从 ESTABLISHED 的状态变成 FIN_WAIT2 并且连接状态没有后续迁移,而对端的连接状态则是从 ESTABLISHED 变成了 CLOSE_WAIT 。

后来发现这和 TCP/IP 栈的4次挥手断开连接有关,列出一些踩坑时的收获。

先看一张 Socket 关闭连接的状态迁移路径图:

在 Client 端调用 socketclose() 时,首先会往对端(即 Server 端)发送一个 FIN 包,接着将自身的状态置为 FIN_WAIT1 ,此时主动关闭端(即 Client 端)处于持续等待接收对端的响应 FIN 包的 ACK 回应状态,此时对端的状态是处于 ESTABLISHED ,一旦收到了 Client 发来的 close 连接请求,就回应一个 FIN 包,表示收到该请求了,并将自身状态置为 CLOSE_WAIT ,这时开始等待 Server 端的应用层向 Client 端发起 close 请求。

这时 Client 端一旦收到 Server 端对第一个 FIN 包的回应 ACK 就会将进入下一个状态 FIN_WAIT_2 来等待 Server 发起断开连接的 FIN 包。在FIN_WAIT_1 的 time_wait 中, Server 端会发起 close 请求,向 Client 端发送 FIN 包,并将自身状态从 CLOSE_WAIT 置为 LAST_ACK ,表示 Server 端的连接资源开始释放了。同时 Client 端正处于 FIN_WAIT2 状态,一旦接收到 Server 端的 FIN 包,则说明 Server 端连接已释放,接着就可以释放自身的连接了,于是进入 TIME_WAIT 状态,开始释放资源,在经过设置的 2个 MSL 时间后,状态最终迁移到 CLOSE 说明连接成功关闭,一次 TCP 4次挥手 关闭连接的过程结束。

通常会出现状态滞留的情况有下面几种:

此外,如果在单台服务器上并且不做负载均衡而处理大量连接的话,可以在 /proc/sys/net/ipv4/ip_local_port_range 中减少端口的极限值,限制每个时间段的最大端口使用数,从而保证服务器的稳定性,一旦出现大量的 TIME_WAIT 阻塞后续连接,是比较致命的。

此外还遇到了另一个小问题,在关闭连接时,一开始用的是 socketterminate() ,然而 netstat 时却发现大量连接没有释放,后来发现 Python Socket 的 terminate() 只是发送 socketSHUT_WR 和 socketSHUT_RD 来关闭通道的读写权限而并没有释放连接句柄。导致了连接已经无法使用,但仍然处于 ESTABLISHED 状态。

解决方法就是使用 socketclose() 来替换 socketterminate()

后来又看到如果是 DDoS 攻击的话,可能会阻塞住 socketclose() ,导致后续连接未关闭,大量流量进入服务器。

所以比较好的方式是在 socketclose() 之前先调用 socketterminate() 关闭通道的读写权限,再调用 socketclose()


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/13487381.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-08-16
下一篇 2023-08-16

发表评论

登录后才能评论

评论列表(0条)

保存