web-dev-qa-db-fra.com

Message d'erreur Android DatagramSocket: EADDRINUSE (adresse déjà utilisée)

J'essaie d'écrire une application de chat Android simple. J'ai créé une classe de service qui gère toutes les communications en réseau. La liaison DatagramSocket est dans un thread séparé. Une fois que je reçois cette erreur et que l'application se bloque:

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)

et c'est le code qui le produit. L'erreur se produit sur la ligne avec new DatagramSocket Comment puis-je éviter cette erreur? Je vous remercie.

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

Vous devez définir SO_REUSEADDR avant de lier. Ne spécifiez pas de port dans le constructeur - créez plutôt une socket non liée avec DatagramSocket(null) , puis définissez les options, puis bind() explicitement.

16
Nikolai Fetissov

Depuis que Sean a demandé le code, j'ai traduit la réponse de Nikola au code suivant, qui est similaire à ce que j'utilise dans mon application, au cas où cela serait utile:

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

Une autre raison à laquelle j'ai fait face,

Si vous accédez à une méthode qui utilise votre socket à partir d’un thread externe, vous devez vous assurer que le thread n’accédera pas à la méthode plus d’une fois dans le même temps (ou, dans un autre mot, ne créera pas plus d’un socket. time), et malgré les méthodes d'envoi et de réception de DatagramSocket sont threadsafe , la construction de l'objet DatagramSocket ne l'est pas, il vous suffit donc de synchroniser la méthode capable de créer le socket DatagramSocket:

synchronized public void my_datagram_socket() throws Exception{

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

}
0
Muhammed Refaat