在Linux平台上使用套接字时是否存在文件描述符泄漏问题?

6
如果我通过调用如下代码打开和关闭一个套接字:
Socket s = new Socket( ... );
s.setReuseAddress(true);
in = s.getInputStream();
...
in.close(); 
s.close();      

Linux指出这个套接字仍然处于打开状态,或者至少连接的文件描述符仍然存在。当使用lsof查询此进程的打开文件时,会出现已关闭连接的条目:

COMMAND  PID   USER   FD   TYPE DEVICE     SIZE   NODE NAME
java    9268 user    5u  sock    0,4           93417 can't identify protocol

这个条目会一直保留,直到程序关闭。有没有其他方法来最终关闭套接字?我有点担心我的Java应用程序可能会阻塞太多文件描述符。这种情况可能吗?或者即使设置了ReuseAdress,Java也会保留这些套接字以便重复使用吗?

5个回答

5
如果这些套接字都处于TIME_WAIT状态,那么这是正常的,至少在一段时间内是这样的。请使用netstat进行检查;套接字通常会在几分钟内挂起,以确保从套接字传输的残留数据成功丢弃,然后才能将端口重新用于新套接字。

同意 - 这是要检查的第一件事。几分钟后,套接字应该消失,然后您的程序才能终止。 - Neil Coffey
作者指出,这些条目会一直保留,直到程序关闭,尽管我猜他并没有具体说明是否超过几分钟。 - Ry4an Brase
是的,我看到了“程序关闭”的那部分,但不确定。 - Richard Campbell

3

您也可以检查/proc/<pid>/fd,该目录包含您当前打开的所有文件描述符。如果在关闭套接字后某个文件消失,您将不会遇到任何问题(至少不会影响您的文件描述符 :)。


1

我认为这不是你的程序问题。

在SUN_Java中,加载了与socket相关的本地库后,将创建一个MAGIC_SOCK fd。

在MAGIC_SOCK上写入将导致连接重置异常,而在MAGIC_SOCK上读取将导致EOF。

magic_sock的对等方已完全关闭,并且magic_sock本身处于半关闭状态,状态将保持为“无法识别的协议”。


0
也许它是某些其他协议的套接字(“无法识别协议”?)在实现中内部使用来执行某些操作,第一个套接字会被创建。
你是否尝试过反复创建和关闭套接字,以查看这些套接字是否真的持久存在?这似乎很可能是一次性事件。
Java 可能在内部为许多事情使用套接字 - 它们可能是 Unix、Netlink(在 Linux 下)或某种其他类型的套接字。

0
创建一个小的bash脚本来监视某个应用程序或进程的打开套接字,并在测试Java应用程序时让它运行。
我怀疑这件事中是否存在任何泄漏问题,因为套接字在Linux/Unix世界中被广泛使用,这种问题很快就会浮出水面。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接