代码之家  ›  专栏  ›  技术社区  ›  Gubatron

Android 2.0.1(目前在Droid上)的多播中断了吗?还是我丢失了什么?

  •  5
  • Gubatron  · 技术社区  · 15 年前

    这段代码在Ubuntu、Windows和Mac OS X上都能很好地工作。它还可以与运行Android 2.1.1的NexusOne一起工作。

    我开始发送和监听多播数据报,所有的计算机和NexusOne都能完美地看到彼此。然后我 在机器人上运行相同的代码 (固件2.0.1),以及 每个人都会收到机器人发送的信息包,但机器人只会听自己的信息包。 .

    这就是 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()

    对于一个 组播 接收器, ONIN() 看起来有些东西 这样地:

    _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 回复  |  直到 13 年前
        1
  •  0
  •   Gubatron    15 年前

    我已经实现了另一个测试,这次使用的是UDP 广播 . 它起作用了。

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