Multicast не работает для Android 2.0.1 (в настоящее время на DROID) или я что-то упустил? - PullRequest
5 голосов
/ 10 марта 2010

Этот код отлично работает в Ubuntu, Windows и Mac OS X. Он также отлично работает с Nexus One под управлением Android 2.1.1.

Я начинаю отправлять и прослушивать многоадресные дейтаграммы, и все компьютеры и Nexus One будут отлично видеть друг друга. Затем я запускаю тот же код на Droid (Прошивка 2.0.1), и каждый получит пакеты, отправленные Droid, но дроид будет прослушивать только свои собственные пакеты .

Это run() метод потока, который постоянно прослушивает многоадресную группу для входящих пакетов, отправленных этой группе.

Я выполняю свои тесты в локальной сети, в которой включена поддержка многоадресной рассылки в маршрутизаторе. Моя цель состоит в том, чтобы устройства встречались друг с другом при подключении к сети путем передачи пакетов в многоадресную группу.

public void run() {
    byte[] buffer = new byte[65535];
    DatagramPacket dp = new DatagramPacket(buffer, buffer.length);

    try {
        MulticastSocket ms = new MulticastSocket(_port);
        ms.setNetworkInterface(_ni); //non loopback network interface passed
        ms.joinGroup(_ia); //the multicast address, currently 224.0.1.16
        Log.v(TAG,"Joined Group " + _ia);

        while (true) {
            ms.receive(dp);
            String s = new String(dp.getData(),0,dp.getLength());
            Log.v(TAG,"Received Package on "+ _ni.getName() +": " + s);
            Message m = new Message();
            Bundle b = new Bundle();
            b.putString("event", "Listener ("+_ni.getName()+"): \"" + s + "\"");
            m.setData(b);
            dispatchMessage(m); //send to ui thread
        }
    } catch (SocketException se) {
        System.err.println(se);
    } catch (IOException ie) {
        System.err.println(ie);
    }
}

Это код, который отправляет многоадресную дейтаграмму из каждого доступного сетевого интерфейса (это не интерфейс обратной связи).

public void sendPing() {
    MulticastSocket ms = null;
    try {
        ms = new MulticastSocket(_port);
        ms.setTimeToLive(TTL_GLOBAL);

        List<NetworkInterface> interfaces = getMulticastNonLoopbackNetworkInterfaces();
        for (NetworkInterface iface : interfaces) {
            //skip loopback
            if (iface.getName().equals("lo"))
                continue;
            ms.setNetworkInterface(iface);
            _buffer = ("FW-"+ _name +" PING ("+iface.getName()+":"+iface.getInetAddresses().nextElement()+")").getBytes();
            DatagramPacket dp = new DatagramPacket(_buffer, _buffer.length,_ia,_port);
            ms.send(dp);
            Log.v(TAG,"Announcer: Sent packet - " + new String(_buffer) + " from " + iface.getDisplayName());
        }
    } catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e2) {
        e2.printStackTrace();
    }
}

Обновление (2 апреля 2010 г.) Я нашел способ использовать сетевой интерфейс Droid для связи с помощью Multicast: WifiManager.MulticastLock .

MulticastLock _wifiMulticastLock = ((WifiManager) context.getSystemService(Context.WIFI_SERVICE)).createMulticastLock("multicastLockNameHere");
_wifiMulticastLock.acquire();

Тогда, когда вы закончите ...

if (_wifiMulticastLock != null && _wifiMulticastLock.isHeld())
    _wifiMulticastLock.release();

После того, как я это сделал, Droid начал отправлять и получать UDP-дейтаграммы в многоадресной группе.

Обновление июль-6-2010

Для моего запроса, вот мой текущий код, существует следующий метод для абстрактного класса, который может использоваться как для широковещательных, так и для многоадресных приемников.

public void run() {
    onInit();
    try {
        byte[] data = new byte[65535];
        while (isProcessing()) {
            try {
                DatagramPacket receivedDatagram = new DatagramPacket(data, data.length);
                _socket.receive(receivedDatagram);
                onDatagramReceived(receivedDatagram);
                data = new byte[65535]; // This pattern is for saving memory allocation.
            } catch (InterruptedIOException e) {
                if (!isProcessing())
                    break;
            }
        } // while

    } catch (Exception e) {
        Log.e(TAG, e.getMessage(), e);
    } finally {
        onStop();
        _socket.close();
        _socket.disconnect();
    }
}

Ваши классы расширения должны реализовывать onInit() и onDatagramReceived()

Для приемника Multicast onInit() выглядит примерно так следующим образом:

_socket = new MulticastSocket(PORT_MULTICAST);
InetAddress groupAddress = InetAddress.getByAddress(MULTICAST_GROUP_ADDRESS); 
InetAddress groupInetAddress = FrostWireUtils.fastResolveAddress(groupAddress); //reflection hack to not resolve ips
try {
    _socket.setSoTimeout(500);
    _socket.setTimeToLive(MULTICAST_TTL_GLOBAL);
    _socket.setReuseAddress(true);
    _socket.setNetworkInterface(
        WifiUtils.getWifiNetworkInterface());
    _socket.joinGroup(groupInetAddress);
    WifiUtils.lockMulticast();
} catch (Exception e) {
    Log.e(TAG, e.getMessage(), e);
}

1 Ответ

0 голосов
/ 10 марта 2010

Я реализовал еще один тест, на этот раз с использованием UDP Broadcast . Это работает.

Вывод: Насколько мне известно, телефоны Motorola Droid с прошивкой 2.0.1 не поддерживают многоадресную рассылку, но вы всегда можете использовать обычные DatagramPackets для широковещательного адреса.

...