linux 如何删除CLOSE_WAIT套接字连接

dvtswwa3  于 2022-12-22  发布在  Linux
关注(0)|答案(7)|浏览(1279)

我写了一个小程序,可以在特定端口上与服务器交互。该程序工作正常,但是:
一旦程序意外终止,并且套接字连接显示为CLOSE_WAIT状态,如果我试图运行一个程序,它会挂起,我必须强制它关闭,这会累积更多的CLOSE_WAIT套接字连接。
有办法清除这些连接吗?

v09wglhw

v09wglhw1#

CLOSE_WAIT意味着你的程序还在运行,并且还没有关闭套接字(内核正在等待它关闭套接字)。将-p添加到netstat以获得pid,然后更强制地终止它(如果需要,使用SIGKILL)。这应该会摆脱你的CLOSE_WAIT套接字。你也可以使用ps来找到pid。
SO_REUSEADDR适用于服务器和TIME_WAIT插槽,因此不适用于此处。

hgqdbh6s

hgqdbh6s2#

Crist Clark所述。
CLOSE_WAIT意味着连接的本地端已经从另一端接收到FIN,但是OS正在等待本地端的程序实际关闭其连接。
问题是在本地计算机上运行的程序没有关闭套接字。这不是TCP调整问题。当程序保持连接打开时,连接可以(并且非常正确地)永远处于CLOSE_WAIT状态。
一旦本地程序关闭套接字,操作系统就可以将FIN发送到远程终端,在等待FIN的ACK时,远程终端会将您转换到LAST_ACK状态。一旦接收到FIN的ACK,连接就会完成并从连接表中删除(如果您的终端处于CLOSE_WAIT状态,则不会处于TIME_WAIT状态)。

0md85ypi

0md85ypi3#

您可以使用ss命令强制关闭套接字。ss命令是一个实用程序,允许您转储套接字统计信息并显示有关网络连接、路由表和各种其他网络相关信息的信息。它类似于netstat命令,但通常更快、更有效。
要使用ss命令强制关闭处于CLOSE_WAIT状态的套接字,可以使用--tcp选项指定要查看TCP套接字,使用state CLOSE-WAIT选项指定仅要查看处于CLOSE_WAIT状态的套接字。例如:

$ ss --tcp state CLOSE-WAIT

这将显示处于CLOSE_WAIT状态的所有TCP套接字的列表。
要强制关闭这些套接字,可以使用--kill选项。这将向套接字发送信号,使其关闭。例如:

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

还可以使用--tcp选项根据各种条件筛选要关闭的套接字。例如,可以使用dport选项指定特定的端口号,或使用dst选项指定特定的目标IP地址。例如:

$ ss --tcp state CLOSE-WAIT '( dport = 22 or dst 1.1.1.1 )' --kill

这将强制关闭连接到端口22或目标IP地址为1.1.1.1的所有处于CLOSE_WAIT状态的TCP套接字。
请务必注意,使用ss命令强制关闭套接字可能会产生意外后果,因为它可能会中断正在进行的网络连接。通常,谨慎使用此命令是一个好主意,并且仅在必要时才使用。

kmbjn2e3

kmbjn2e34#

即使太多的CLOSE_WAIT连接意味着你的代码在第一次就有问题,这也是可以接受的,不是好的做法。
您可能需要查看:https://github.com/rghose/kill-close-wait-connections
这个脚本所做的是发送连接所等待的ACK。
这对我很有效。

yhqotfr8

yhqotfr85#

我的一个最新的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

this post中所述,您可以使用/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`
l5tcr1uw

l5tcr1uw6#

需要说明的是,客户端和服务器端的Socket示例都需要显式调用close(),如果只有一端调用close(),那么socket也会保持CLOSE_WAIT状态。

ggazkfy8

ggazkfy87#

同样值得注意的是,如果你的程序产生了一个新进程,这个进程可能会继承你所有打开的句柄。即使在你自己的程序关闭之后,那些继承的句柄仍然可以通过孤儿子进程存活。它们不一定会在netstat中显示完全相同的内容。但无论如何,当这个子进程存活时,套接字将在CLOSE_WAIT中挂起。
我曾经运行过ADB。如果ADB没有运行,它会自己生成一个服务器进程。这最初继承了我所有的句柄,但在我调查时没有显示为拥有其中任何一个(macOS和Windows都是如此--不确定Linux)。

相关问题