Android: java.net.DatagramSocket.bind: недопустимое исключение аргумента - PullRequest
7 голосов
/ 18 марта 2011

Справочная информация: я пишу простое приложение UDP для проверки связи с бета-сервером, которым я управляю каждую минуту или около того, чтобы сообщить мне, что он все еще работает (я не могу включить проверку связи на сервере для тех, кто интересуется). Я планирую запустить это на своем телефоне, чтобы предупредить меня, когда сервер больше не отвечает.

Я пытаюсь использовать, казалось бы, простой java.net.DatagramSocket как таковой:

    try
    {
        socket = new DatagramSocket();
        socket.bind(null);
    } 
    catch (SocketException e)
    {
        System.out.println(e.toString());
        throw e;
    }

Позвольте мне также сказать, что я включил разрешения доступа в Интернет через манифест android, и если я удаляю для этого условие использования, я получаю ошибку разрешений, поэтому я уверен, что она работает нормально. Когда я загружаю этот код на виртуальное устройство Android (AVD) и выполняю его, при вызове bind () мне представляется следующее исключение:

03-17 19: 07: 39.401: INFO / System.out (338): java.net.BindException: неверный аргумент

Согласно этой документации, нулевой аргумент верен:

публичное связывание void (SocketAddress localAddr)

С: Уровень API 1

Связывает этот сокет с локальным адресом и портом, указанными localAddr. Если это значение равно нулю, используется любой свободный порт на действительном локальном адресе .

Но не доверяя документации, я решил перечислить IP-адреса на моем устройстве следующим образом:

    ArrayList<NetworkInterface>  allInterfaces = Collections.list(NetworkInterface.getNetworkInterfaces());

    NetworkInterface eth = allInterfaces.get(0);

    InetSocketAddress addr = new InetSocketAddress(eth.getInetAddresses().nextElement(), port);

    try
    {
        socket = new DatagramSocket();
        socket.bind(addr);
    } 
    catch (SocketException e)
    {
        System.out.println(e.toString());
        throw e;
    }

Когда я перебираю код, он отлично работает, и я вижу два IP-адреса на AVD, но я получаю точно такое же исключение при вызове bind (). Кто-нибудь там видит, чего мне не хватает? Я продолжу исследовать и, надеюсь, опубликую решение моей собственной проблемы, но я надеюсь, что кто-нибудь сможет мне помочь.

Ответы [ 2 ]

9 голосов
/ 18 марта 2011

[Отредактировано: если вы увидели мой предыдущий ответ, я сделал классическую ошибку отладки, меняя две переменные в одном тесте, и именно эта проблема решила мою проблему.]

Я нашел проблему.Это способ, которым я объявляю DatagramSocket, который, кажется, вызывает проблемы.Если я использую DatagramChannel, чтобы открыть DatagramSocket следующим образом, то вызов bind () будет успешным.

      DatagramChannel channel = DatagramChannel.open();
      DatagramSocket socket = channel.socket();
2 голосов
/ 04 марта 2016

Я также наткнулся на эту проблему и нашел причину: если вы вызываете конструктор без параметров new DatagramSocket(), это создает «сокет дейтаграммы UDP , который связан с любым доступным портом на локальномхост с использованием подстановочного адреса "(согласно документации API).Так что это на самом деле означает, что сокет уже связан.Мое «исправление» для этого заключается в следующем:

        SocketAddress socketAddress = new SocketAddress(yourInetAddress, yourPort);
        DatagramSocket serverSocket = new DatagramSocket(null);
        serverSocket.bind(socketAddress);

Это явно создает несвязанный сокет (через конструктор DatagramSocket (SocketAddress localAddr)), что позволяет связывать сокет по очереди.

Вероятно, это более элегантное решение, чем создание ненужного канала.

PS: как ни странно, именно в этом DatagramSocket отличается от TCP ServerSocket: конструктор без параметров последнего создаст несвязанный ServerSocket,не вызывает эту проблему.

...