Android 2.0.1(当前在 DROID 上)的多播是否已损坏,还是我遗漏了什么?

发布于 2024-08-24 12:28:16 字数 4568 浏览 6 评论 0原文

此代码在 Ubuntu、Windows 和 Mac OS X 中完美运行。它在运行 Android 2.1.1 的 Nexus One 上也能正常运行。

我开始发送和侦听多播数据报,所有计算机和 Nexus One 都能完美地看到对方。然后我在 Droid 上运行相同的代码(固件 2.0.1),每个人都会收到 Droid 发送的数据包,但 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();
    }
}

更新(2010 年 4 月 2 日) 我找到了一种让 Droid 的网络接口使用多播进行通信的方法: WifiManager.MulticastLock

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

然后当你完成后...

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

在我完成此操作后,Droid 开始在多播组上发送和接收 UDP 数据报。

2010 年 7 月 6 日更新

根据请求,这是我当前的代码,下一个方法存在于可用于广播和组播接收器的抽象类上。

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()

对于 多播 接收器,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);
}

This code works perfectly in Ubuntu, Windows, and Mac OS X. It also works fine with a Nexus One running Android 2.1.1.

I start sending and listening multicast datagrams, and all the computers and the Nexus One will see each other perfectly. Then I run the same code on a Droid (Firmware 2.0.1), and everybody will get the packets sent by the Droid, but the droid will listen only to its own packets.

This is the run() method of a thread that's constantly listening on a Multicast group for incoming packets sent to that group.

I'm running my tests on a local network where I have multicast support enabled in the router.
My goal is to have devices meet each other as they come online by broadcasting packages to a multicast group.

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

This is the code that sends the Multicast Datagram out of every valid network interface available (that's not the loopback interface).

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();
    }
}

Update (April 2nd 2010)
I found a way to have the Droid's network interface to communicate using Multicast: WifiManager.MulticastLock.

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

Then when you're done...

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

After I did this, the Droid started sending and receiving UDP Datagrams on a Multicast group.

Update Jul-6-2010

Per request, here's my current code, the next method exists on an abstract class that can be used for both Broadcast and Multicast receivers.

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();
    }
}

Your extending classes should implement onInit() and onDatagramReceived()

For a Multicast receiver, onInit() looks something like this:

_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);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

稚气少女 2024-08-31 12:28:16

我实施了另一个测试,这次使用 UDP 广播
有用。

结论: 据我所知,固件 2.0.1 的 Motorola Droid 手机不支持多播,但您始终可以在广播地址上使用常规 DatagramPackets。

I've implemented another test, this time using UDP Broadcast.
It works.

Conclusion: To the extent of my knowledge Motorola Droid phones on firmware 2.0.1 don't support multicast, but you can always use regular DatagramPackets on the broadcast address.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文