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 是否保留这些套接字以重新使用它们?

4

5 回答 5

5

如果这些套接字都处于 TIME_WAIT 状态,这是正常的,至少有一小会儿。用 netstat 检查;套接字通常会挂起几分钟,以确保在将端口重新用于新套接字之前成功丢弃来自套接字的散乱数据。

于 2009-01-09T21:40:48.997 回答
3

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

于 2009-01-09T23:04:55.300 回答
1

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

在 SUN_Java 中,当 socket 相关的 native lib 加载时,会创建一个 MAGIC_SOCK fd。

在 MAGIC_SOCK 上写入将导致 Connect Rest 异常,在 MAGIC_SOCK 上读取将导致 EOF。

magic_sock 的 peer 已经完全关闭,magic_sock 本身是 half_closed,状态会一直保持“无法识别协议”。

于 2011-12-09T08:08:23.507 回答
0

也许它是某个其他协议的套接字(“无法识别协议”嗯?)在实现内部用于执行某些操作,该套接字是在第一个套接字上创建的。

您是否尝试过反复创建套接字并关闭它们,以查看这些套接字是否真的存在?这似乎是一次性的。

Java 可能在内部使用套接字做很多事情——它们可能是 Unix、Netlink(在 Linux 下)或其他类型的套接字。

于 2009-01-09T21:19:39.897 回答
0

创建一个小的 bash 脚本来监视某个应用程序或 pid 的打开套接字,并让它在测试您的 java 应用程序时运行。

无论如何,我怀疑这件事是否存在任何类型的泄漏,因为套接字在 linux/unix 世界中非常常用,而且这种问题会很快冒出来

于 2009-01-09T22:47:29.140 回答