如何删除CLOSE_WAIT套接字连接


91

我编写了一个与特定端口上的服务器交互的小程序。该程序工作正常,但是:

一旦程序意外终止,并且此套接字连接一直处于CLOSE_WAIT状态显示。如果尝试运行程序,它将挂起,并且必须强制将其关闭,这会累积更多的 CLOSE_WAIT套接字连接。

有没有办法清除这些连接?


4
您不能(也不应该)。CLOSE_WAIT是TCP定义的一种状态,用于关闭连接,等待对方确认。
vonbrand 2013年

1
另请参见unix.stackexchange.com/questions/10106/……我不会重复投票,因为最终它会以离题的方式结束问题。
derobert

3
@vonbrand不,不是这样。这是连接的状态,该连接已被对等方关闭,正在等待本地应用程序结束其连接。
罗恩侯爵

如果您使用Commons HttpClient,则nuxeo.com/blog/…具有很多相关信息。从RFC 2616第14节:不支持持久连接的HTTP / 1.1应用程序必须在每条消息中都包括“关闭”连接选项。
Mayank Ahuja

Answers:


79

CLOSE_WAIT表示您的程序仍在运行,并且尚未关闭套接字(内核正在等待它关闭)。添加-pnetstat以获取该pid,然后更加有力地将其杀死(SIGKILL如果需要的话)。那应该摆脱您的CLOSE_WAIT套接字。您也可以使用ps来查找pid。

SO_REUSEADDR用于服务器和TIME_WAIT套接字,因此不适用于此处。


2
好吧...如果该程序打开了很多连接,则挂起该过程可能不是最好的,只有少数几个留在“ CLOSE_WAIT”中:在这种情况下,杀死该进程可能是完全不可能的或不合适的(该程序仍然有效,并且提供服务以及其他联系方式)。仅关闭挂起的连接会更合适。但实际上,通常是程序本身并未在本地关闭connectino(CLOSE_WAIT表示它从另一端收到了“ FIN”,程序只需要在本地关闭连接)。一个错误报告可能是适当的
Olivier Dulac

40

正如克里斯蒂·克拉克Crist Clark)所描述的。

CLOSE_WAIT表示连接的本地端已从另一端收到FIN,但是OS正在等待本地端的程序实际关闭其连接。

问题是您在本地计算机上运行的程序没有关闭套接字。这不是TCP调整问题。在程序使连接保持打开状态的同时,连接可以(并且相当正确)永远停留在CLOSE_WAIT中。

本地程序关闭套接字后,操作系统可以将FIN发送到远程端,当您等待FIN的ACK时,该远程端会将您转换为LAST_ACK。收到连接后,连接完成,并从连接表中删除(如果您的终端处于CLOSE_WAIT,则不会以TIME_WAIT状态结束)。


4
如何关闭插座?
Divyang Shah

1
关闭打开的插座上的手柄。使用close()closesocket(),取决于使用的平台。
雷米·勒博

8

我在最新的Tomcat服务器(7.0.40)上也遇到了同样的问题。连续几天无响应。

要查看打开的连接,可以使用:

sudo netstat -tonp | grep jsvc | grep --regexp="127.0.0.1:443" --regexp="127.0.0.1:80" | grep CLOSE_WAIT

正如提到的这个职位,你可以使用/proc/sys/net/ipv4/tcp_keepalive_time,以查看值。该值似乎以秒为单位,默认为7200(即2小时)。

要更改它们,您需要进行编辑/etc/sysctl.conf

Open/create `/etc/sysctl.conf`
Add `net.ipv4.tcp_keepalive_time = 120` and save the file
Invoke `sysctl -p /etc/sysctl.conf`
Verify using `cat /proc/sys/net/ipv4/tcp_keepalive_time`

4
答案令人困惑。您说无响应状态已经走了好几天了。但是您还尝试将保持活动时间设置为仅120秒。即使使用默认值(7200秒),它也不应该持续几天,对吗?
fanchyna 2015年

8

即使CLOSE_WAIT连接过多,也意味着您的代码在开始时就出现了问题,这不是很好的做法。

您可能要签出:https : //github.com/rghose/kill-close-wait-connections

该脚本的作用是发出连接正在等待的ACK。

这对我有用。


您将行为发送到关闭等待套接字。与不起作用..如果起作用,为什么?
Chinaxing

我猜想,操作系统已经将FIN发送到远程主机。远程主机可能无法使用套接字期望的ACK进行回复。
海市rage楼

是的,没错(根据内核代码)。但是我也怀疑您发送的数据包的SEQ为“ 10”,内核不检查吗?
Chinaxing

可能不会。我想我尝试了许多随机数,它们似乎起作用了。
海市


3

您可以使用ss命令强制关闭套接字;该ss命令是用于转储套接字统计信息并以类似于netstat的方式(尽管更简单,更快)显示信息的工具。

要杀死处于CLOSE_WAIT状态的任何套接字,请以root用户身份运行此套接字

$ ss --tcp state CLOSE-WAIT --kill

1

还值得注意的是,如果您的程序产生了一个新进程,则该进程可能会继承所有打开的句柄。即使在您自己的程序关闭后,那些继承的句柄仍然可以通过孤立的子进程存活。而且它们不一定在netstat中显示完全相同。但是,同样的,当该子进程处于活动状态时,套接字将在CLOSE_WAIT中徘徊。

我遇到了运行亚行的情况。如果ADB本身尚未运行,则它本身会生成一个服务器进程。这最初继承了我的所有句柄,但在我进行调查时并没有显示为拥有它们(对于macOS和Windows都是一样的-不确定Linux)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.