我的应用非常简单。客户端将连接到LocalServerSocket(Unix域套接字)并发送一些数据并断开连接。如果此过程重复超过1024次,则服务器在接受新客户端时会抛出java.io.IOException: socket failed: EMFILE (Too many open files)
。
我在这里上传了我的演示代码 http://speedy.sh/NBSjr/SocketIssue.zip
您可以在代码中看到客户端在与服务器建立另一个连接之前关闭了连接。在logcat中,您可以看到服务器中的FileDescriptor数量在增加,并且在第1023次客户端连接时崩溃。
如何解决此问题?请建议
我在运行Android 4.3的三星S4上尝试过它。它似乎正在重用文件描述符,我的演示应用程序可以运行几个小时!
于2014-05-19更新
如果您没有运行Android 4.4.2的设备,可以在运行Android 4.4.2的模拟器上试用此代码
答案 0 :(得分:1)
我需要一段时间来运行你的代码,并用e.printStack();
填充所有try-catch块以查看是否忽略了一些异常,但没有运气,我无法获得相同的{{1它运行了1个多小时,没有异常。
我有一个问题可能会有所帮助,也就是说我找不到任何代码来计算IOException
,也许你没有上传正确版本的代码,或者你误解了这个数字对FileDescriptor
的计数log 05-18 05:18:50.409: V/SocketCmdServer(636): Incoming client fd:FileDescriptor[35]
,我读了FileDescriptor
toString()
的源代码,该数字不是计数器,而是fd类型。
FileDescriptor
在Linux上运行的任何java vms都可能有最大套接字连接号,因为linux将socket连接作为文件,你可以通过这些linux cmds看到最大数量:
/**
* The Unix file descriptor backing this FileDescriptor.
* A value of -1 indicates that this FileDescriptor is invalid.
*/
private int descriptor = -1;
@Override public String toString() {
return "FileDescriptor[" + descriptor + "]";
}
(PS:你可能需要一个busybox才能在android中获得完整的linux cmds)
并且不建议修改最大文件编号。
首先,我的建议如下:
1)尽量避免达到系统设定的插座连接的最大数量限制
2)填写所有try-catch块以打印轨道堆栈以查看是否成功关闭套接字
cat /proc/sys/fs/file-max