2014-05-09 16 views
5

Meine App ist ziemlich einfach. Der Client stellt eine Verbindung zu einem LocalServerSocket (Unix Domain Socket) her und sendet einige Daten und trennt die Verbindung. Wenn dieser Prozess mehr als 1024 Mal wiederholt wird, löst der Server java.io.IOException: socket failed: EMFILE (Too many open files) aus, wenn ein neuer Client akzeptiert wird.EMFILE (zu viele offene Dateien) Fehler beim Verbinden mit LocalServerSocket?

Ich habe meine Demo-Code hier hochgeladen http://speedy.sh/NBSjr/SocketIssue.zip

Sie können in den Code sehen, dass der Client die Verbindung, bevor Sie eine weitere Verbindung zum Server hergestellt wird geschlossen. Im Logcat können Sie sehen, dass die Anzahl der FileDescriptoren auf dem Server zunimmt und abstürzt, wenn der Client sich zum 1023. Mal verbindet.

Wie behebe ich dieses Problem? Bitte Beratung

Ich habe es auf Samsung S4 mit Android 4.3 versucht. Es scheint, dass es Dateideskriptoren wiederverwendet und meine Demo-App kann stundenlang laufen!

aktualisiert am 2014-05-19

Wenn Sie mit Android nicht über ein Gerät haben 4.4.2 können Sie diesen Code versuchen, auf einem Emulator mit Android 4.4.2

+0

Lesen Sie das Thema Sie 1024 simultan Verbindungen vorschlagen. Sie geben LocalServer die Schuld, wo Sie vielleicht FileDescriptor verantwortlich machen müssen. Wozu brauchst du diesen Deskriptor? Sie haben nur einen Aufruf von closeClient() auf dem Server, der niemals aufgerufen wird. Da der Server einen Client nicht behandelt, nachdem eine Nachricht empfangen und zurückgegeben wurde, können Sie den Server auch den Client schließen lassen. Setzen Sie im try-Block nach oos.flush() den Befehl closeClient(). Vielleicht schließt das den Dateideskriptor. – greenapps

+0

Ich habe einen Server. Ein oder mehrere Clients können sich mit diesem Server verbinden. Ein Client verbindet einige Daten und trennt die Verbindung. Wenn dies mehr als 1024 mal passiert, löst es java.io aus.IOException: socket failed: EMFILE (Zu viele offene Dateien) – kakopappa

+0

Ja, ich habe das verstanden, wie Sie in meinem Kommentar lesen können. Aber hast du meinen Vorschlag umgesetzt und es versucht? Bitte reagieren Sie auf Vorschläge. – greenapps

Antwort

1

ich eine Weile dauern, um deinen Code zu starten und alle try-catch-Blöcke mit e.printStack(); zu füllen, um zu sehen, ob einige Ausnahmen ignoriert werden, aber kein Glück, kann ich nicht IOException bekommen, es hat mehr als 1 Stunde ohne Ausnahme gelaufen.

ich eine Frage haben, die etwas Hilfe tun kann, also ich keinen Code FileDescriptor zählen finden, vielleicht haben Sie nicht die richtige Version des Codes laden oder verwechselte Sie die Nummer in log 05-18 05:18:50.409: V/SocketCmdServer(636): Incoming client fd:FileDescriptor[35] für die Anzahl von FileDescriptor, ich lese den Quellcode toString() von FileDescriptor, die Nummer ist kein Zähler, sondern ein Fd-Typ.

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

jeder Java-VMs auf Linux laufen kann die max Buchse Connetion-Nummern haben, beacuse Linux-take-Socket-Verbindung als eine Datei, können Sie die maximale Anzahl über diese Linux cmds sehen:

cat /proc/sys/fs/file-max 

(PS : möglicherweise benötigen Sie eine busybox, um volle linux cmds in android zu erhalten)

und es wird nicht empfohlen, die maximale Dateinummer zu ändern.

vor allem, ich habe Vorschläge, wie unten:
1) versuchen, die maximale Anzahl Grenze von Socket-Verbindungen durch das System gesetzt zu vermeiden erreichen
2) füllen alle von Ihnen try-catch-Block der Spur zu drucken Stacks zu sehen Sie, ob Sie den Sockel erfolgreich schließen

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

Vielen Dank, dass Sie sich die Zeit genommen haben, dies zu betrachten. Ich habe versucht, versuchen/fangen Methoden, die Sie vorgeschlagen haben. Ich habe keine Fehler beim Schließen der Socket/Streams gesehen. Ich kann dieses Problem auch auf dem Android 4.4-Emulator reproduzieren. Wenn Sie einen Emulator mit Android 4.4 erstellen können Sie in LogCat sehen. Ich habe ein Snap meines LogCat hier http://sharesend.com/cwbpf0bn hochgeladen – kakopappa

Verwandte Themen