2014-05-09 55 views
5

我的应用程序非常简单。客户端将连接到LocalServerSocket(Unix域套接字)并发送一些数据并断开连接。如果此过程重复超过1024次,则服务器在接受新客户端时抛出java.io.IOException: socket failed: EMFILE (Too many open files)连接到LocalServerSocket时EMFILE(太多打开的文件)错误?

我已上载这里 http://speedy.sh/NBSjr/SocketIssue.zip

我的演示代码,你可以在代码中看到,客户端关闭与服务器建立另一个连接之前进行连接。在logcat中,您可以看到服务器中的FileDescriptor计数正在增加,并且在第1023次客户端连接时崩溃。

我该如何解决这个问题?请指教

我在运行Android 4.3的三星S4上试了一下。它似乎是重用文件描述符,我的演示应用程序可以运行几个小时!

更新于2014年5月19日

如果你没有运行的是Android 4.4.2您可以尝试在模拟器上的代码运行的是Android 4.4.2

+0

阅读你建议的1024个主题1024个同时连接。你怪本地服务器,也许你必须责怪FileDescriptor。你需要什么描述符?在服务器中只有一个closeClient()调用永远不会被调用。由于服务器在收到并返回一条消息后不处理客户端,因此可以让服务器关闭客户端。在oos.flush()之后的try块中放置closeClient()。也许这会关闭文件描述符。 – greenapps

+0

我有一台服务器。一个或多个客户端可以连接到该服务器。客户端将连接发送一些数据并断开连接。如果这发生超过1024次,则抛出java.io.IOException:套接字失败:EMFILE(太多打开的文件) – kakopappa

+0

是的,我明白,因为你可以阅读我的评论。但是,您是否实施了我的建议并尝试了?请对建议做出反应。 – greenapps

回答

1

我需要一段时间的设备运行你的代码,并用e.printStack();填充所有的try-catch块来查看是否有一些例外被忽略,但没有运气,我不能得到相同的IOException,它已经运行超过1小时,没有例外。

我有一个疑问,可能会做一些帮助,这是我无法找到任何代码来算FileDescriptor,也许你没有上传代码的正确版本,或者,你记错号码在log 05-18 05:18:50.409: V/SocketCmdServer(636): Incoming client fd:FileDescriptor[35]为计数为FileDescriptor,我读到toString()的源代码FileDescriptor,这个数字不是一个计数器而是一个fd类型。

/** 
* 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 + "]"; 
} 

在Linux上运行的任何Java虚拟机可以有最大插口引黄号码,怎么一回事,因为Linux的取套接字连接为一个文件,你可以看到通过这些Linux的CMDS的最大数量:

cat /proc/sys/fs/file-max 

(PS :您可能需要一个busybox才能在android中获得完整的linux cmds)

并且不建议修改最大文件数。

高于一切,我已经建议如下:
1)尽量避免通过接触系统
2设置套接字连接的最大数量限制)填写大家try-catch块打印的轨道堆栈,以看看你是否成功地关闭了插座

private void connectToServer() { 
     LocalSocket client = null; 
     ObjectOutputStream oos = null; 
     ObjectInputStream ois = null; 
     try { 
      client = new LocalSocket(); 

      Log.v(TAG, "connectToServer # Connect to the server"); 
      client.connect(new LocalSocketAddress(SOCKER_SERVER_NAME)); 

      Log.v(TAG, "connectToServer # Send the command"); 
      oos = new ObjectOutputStream(client.getOutputStream()); 
      oos.writeObject(new String("Hello")); 
      oos.flush(); 

      ois = new ObjectInputStream(client.getInputStream()); 
      Object obj = ois.readObject(); 

      Log.v(TAG, "connectToServer # Response is received"); 
     } 
     catch (Exception e) { 
       Log.e(TAG, "connectToServer # Error:..", e); 
     } 
     finally { 

      // each close() method should be wrapped in seperated try-catch block 
      // or 1 or 2 close() method will be skipped 
      try { 
       if (oos != null) { 
        oos.close(); 
        oos = null; 
       } 
       if (ois != null) { 
        ois.close(); 
        ois = null; 
       } 

       if(client != null) { 
        client.close(); 
        client = null; 
       } 
      } 
      catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
+0

谢谢你花时间看看这个。我尝试使用你建议的try/catch方法。关闭套接字/流时,我没有看到任何错误。我也可以在Android 4.4仿真器上重现此问题。如果您可以使用Android 4.4创建模拟器,您可以在LogCat中看到。我在这里上传了一个我的LogCat的快照http://sharesend.com/cwbpf0bn – kakopappa

相关问题