Linux 如何删除 CLOSE_WAIT 套接字连接

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15912370/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 22:40:22  来源:igfitidea点击:

How do I remove a CLOSE_WAIT socket connection

linuxsockets

提问by Dilletante

I have written a small program that interacts with a server on a specific port. The program works fine, but:

我编写了一个小程序,可以与特定端口上的服务器进行交互。该程序运行良好,但是:

Once the program terminated unexpectedly, and ever since that socket connection is shown in CLOSE_WAITstate. If I try to run a program it hangs and I have to force it close, which accumulates even moreCLOSE_WAITsocket connections.

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

Is there a way to flush these connections?

有没有办法刷新这些连接?

采纳答案by derobert

CLOSE_WAITmeans your program is still running, and hasn't closed the socket (and the kernel is waiting for it to do so). Add -pto netstatto get the pid, and then kill it more forcefully (with SIGKILLif needed). That should get rid of your CLOSE_WAITsockets. You can also use psto find the pid.

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

SO_REUSEADDRis for servers and TIME_WAITsockets, so doesn't apply here.

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

回答by Amil Waduwawara

I'm also having the same issue with a very latest Tomcat server (7.0.40). It goes non-responsive once for a couple of days.

我在最新的 Tomcat 服务器 (7.0.40) 上也遇到了同样的问题。它会在几天内无响应一次。

To see open connections, you may use:

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

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

As mentioned in this post, you may use /proc/sys/net/ipv4/tcp_keepalive_timeto view the values. The value seems to be in seconds and defaults to 7200 (i.e. 2 hours).

正如这篇文章中提到,您可以使用/proc/sys/net/ipv4/tcp_keepalive_time来查看这些值。该值似乎以秒为单位,默认为 7200(即 2 小时)。

To change them, you need to edit /etc/sysctl.conf.

要更改它们,您需要编辑/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`

回答by user2618402

As described by Crist Clark.

正如克里斯特克拉克所描述的那样。

CLOSE_WAIT means that the local end of the connection has received a FIN from the other end, but the OS is waiting for the program at the local end to actually close its connection.

The problem is your program running on the local machine is not closing the socket. It is not a TCP tuning issue. A connection can (and quite correctly) stay in CLOSE_WAIT forever while the program holds the connection open.

Once the local program closes the socket, the OS can send the FIN to the remote end which transitions you to LAST_ACK while you wait for the ACK of the FIN. Once that is received, the connection is finished and drops from the connection table (if your end is in CLOSE_WAIT you do notend up in the TIME_WAIT state).

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

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

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

回答by mirage

Even though too much of CLOSE_WAIT connections means there is something wrong with your code in the first and this is accepted not good practice.

即使过多的 CLOSE_WAIT 连接意味着您的代码在第一个出现问题,这被接受不是好的做法。

You might want to check out: https://github.com/rghose/kill-close-wait-connections

您可能想查看:https: //github.com/rghose/kill-close-wait-connections

What this script does is send out the ACK which the connection was waiting for.

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

This is what worked for me.

这对我有用。

回答by Binita Bharati

It should be mentioned that the Socketinstance in both client and the server end needs to explicitly invoke close(). If only one of the ends invokes close()then too, the socket will remain in CLOSE_WAIT state.

需要说明的是Socket,客户端和服务端的实例都需要显式调用close(). 如果只有一端也调用close(),则套接字将保持在 CLOSE_WAIT 状态。

回答by Ian

It is also worth noting that if your program spawns a new process, that process may inherit all your opened handles. Even after your own program closs, those inherited handles can still be alive via the orphaned child process. And they don't necessarily show up quite the same in netstat. But all the same, the socket will hang around in CLOSE_WAIT while this child process is alive.

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

I had a case where I was running ADB. ADB itself spawns a server process if its not already running. This inherited all my handles initially, but did not show up as owning any of them when I was investigating (the same was true for both macOS and Windows - not sure about Linux).

我有一个案例,我正在运行 ADB。如果 ADB 尚未运行,它本身会生成一个服务器进程。这最初继承了我的所有句柄,但在我调查时并没有显示为拥有它们中的任何一个(macOS 和 Windows 都是如此 - 不确定 Linux)。

回答by Mustapha Hadid

You can forcibly close sockets with sscommand; the sscommand is a tool used to dump socket statistics and displays information in similar fashion (although simpler and faster) to netstat.

可以通过ss命令强行关闭套接字;该ss命令是一个工具,用于转储套接字统计信息并以与 netstat 类似的方式(虽然更简单和更快)显示信息。

To kill any socket in CLOSE_WAIT state, run this (as root)

要终止处于 CLOSE_WAIT 状态的任何套接字,请运行它(以 root 身份)

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