Сообщение об ошибке Android DatagramSocket: EADDRINUSE (адрес уже используется) - программирование
Подтвердить что ты не робот

Сообщение об ошибке Android DatagramSocket: EADDRINUSE (адрес уже используется)

Я пытаюсь написать простое приложение для Android. Я создал класс обслуживания, который обрабатывает всю сетевую связь. Связывание DatagramSocket находится в отдельном потоке. Входите, пока я получаю эту ошибку, и приложение вылетает:

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)

и это код, который его производит. Ошибка возникает в строке с новой DatagramSocket. Как я могу избежать этой ошибки? Спасибо.

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);
            }
        }
4b9b3361

Ответ 1

Перед связыванием необходимо установить SO_REUSEADDR. Не указывайте порт в конструкторе - вместо этого создайте несвязанный сокет DatagramSocket(null), затем установите параметры, затем bind() явно.

Ответ 2

Поскольку Шон попросил код, я перевел Nikola на следующий код, который похож на то, что я использую в своем приложении, если это полезно:

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

Ответ 3

Еще одна причина, по которой я столкнулся,

Если вы обращаетесь к методу, использующему ваш сокет из внешнего потока, вы должны убедиться, что поток не будет обращаться к этому методу более одного раза в одно и то же время (или другими словами не будет создавать сокет более чем один раз), и несмотря на методы отправки и получения DatagramSocket являются потокобезопасными, для построения объекта DatagramSocket нет, поэтому вам нужно просто синхронизировать метод, способный создавать сокет DatagramSocket:

synchronized public void my_datagram_socket() throws Exception{

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

}