it-swarm.com.de

Android DatagramSocket-Fehlermeldung: EADDRINUSE (Adresse wird bereits verwendet)

Ich versuche, eine einfache Android-Chat-App zu schreiben. Ich habe eine Serviceklasse erstellt, die die gesamte Netzwerkkommunikation übernimmt. Die DatagramSocket-Bindung befindet sich in einem separaten Thread. Hin und wieder erhalte ich diesen Fehler und die App stürzt ab:

Java.net.BindException: bind failed: EADDRINUSE (Address already in use)
at libcore.io.IoBridge.bind(IoBridge.Java:89)
at Java.net.PlainDatagramSocketImpl.bind(PlainDatagramSocketImpl.Java:68)
at Java.net.DatagramSocket.createSocket(DatagramSocket.Java:133)
at Java.net.DatagramSocket.<init>(DatagramSocket.Java:78)

und dies ist der Code, der es produziert. Der Fehler tritt in der Zeile mit new DatagramSocket auf. Wie kann ich diesen Fehler vermeiden? Vielen Dank.

private class ComThread extends Thread {

        private static final int BCAST_PORT = 8779;
        DatagramSocket mSocket;
        InetAddress myBcastIP, myLocalIP;

        public ComThread() {

            try {
                myBcastIP = getBroadcastAddress();
                if (D)
                    Log.d(TAG, "my bcast ip : " + myBcastIP);

                myLocalIP = getLocalAddress();
                if (D)
                    Log.d(TAG, "my local ip : " + myLocalIP);

                if (mSocket == null) {
                    mSocket = new DatagramSocket(BCAST_PORT);
                    mSocket.setReuseAddress(true);
                    mSocket.setBroadcast(true);
                }           

            } catch (IOException e) {
                Log.e(TAG, "Could not make socket", e);
            }
        }
17
Sean Kilb

Sie müssen vor dem Binden SO_REUSEADDR einstellen. Geben Sie im Konstruktor keinen Port an - erstellen Sie stattdessen ungebundenes Socket mit DatagramSocket(null) , setzen Sie dann Optionen und dann bind() explizit.

16

Seitdem Sean nach dem Code gefragt hat, habe ich die Antwort von Nikola in den folgenden Code übersetzt, der dem in meiner App verwendeten ähnlich ist, falls es nützlich ist:

if (mSocket == null) {
    mSocket = new DatagramSocket(null);
    mSocket.setReuseAddress(true);
    mSocket.setBroadcast(true);
    mSocket.bind(new InetSocketAddress(BCAST_PORT));
}
27
Hong

Ein anderer Grund, dem ich begegnet bin,

Wenn Sie auf eine Methode zugreifen, die Ihren Socket von einem externen Thread aus verwendet, müssen Sie sicherstellen, dass der Thread nicht mehrmals in derselben Zeit auf die Methode zugreift (oder mit anderen Worten den Socket nicht mehr als einen erstellt.) time) und trotz die Sende- und Empfangsmethoden des DatagramSocket sind threadsicher , die Konstruktion des DatagramSocket-Objekts ist nicht, daher müssen Sie nur die Methode synchronisieren, die den DatagramSocket-Socket erstellen kann:

synchronized public void my_datagram_socket() throws Exception{

  // create the socket
  // operations through the socket
  // whatever you want

}
0
Muhammed Refaat