【问题标题】:Android device not receiving multicast packageAndroid 设备未收到多播包
【发布时间】:2012-11-04 18:55:24
【问题描述】:

我正在开发一个聊天应用程序,Android 客户端将使用多播 (UDP) 交换他们的 IP。

每台设备都会在一个单独的线程中将其 ip 发送到多个客户端(所有运行此应用程序的设备)。将有另一个接收者线程来监听这些多播数据包。这是我的代码。

//多播代码。

DatagramSocket socket = new DatagramSocket(9898);
            byte buff[] = ip.getBytes();
            DatagramPacket packet = new DatagramPacket(buff, buff.length, InetAddress.getByName("224.0.0.1"),9999);
            socket.send(packet);
            socket.close();

//接收方代码

MulticastSocket socket = new MulticastSocket(9999);
        InetAddress group = InetAddress.getByName("224.0.0.1");
        socket.joinGroup(group);

        DatagramPacket packet;

            byte[] buf = new byte[256];
            byte  b = 'x'; //just a separator for time being
            Arrays.fill(buf,b);
            packet = new DatagramPacket(buf, buf.length);
            String received= "";
            while(received!=null)
            {
                socket.receive(packet);
                received = new String(packet.getData());
                received = received.substring(0,received.indexOf('x'));
                this.setIp(received);
                System.out.println("Address: " + received);
            }

        socket.leaveGroup(group);
        socket.close();

问题是每个设备都打印自己的地址。似乎它从不听其他多播包(我的意思是它也应该打印其他 ip)。我也得到一个下面的日志,不确定是否相关。

11-04 23:56:17.985: I/OSNetworkSystem(603): mcastAddDropMembership interfaceIndex=0

任何帮助将不胜感激。

【问题讨论】:

    标签: java android networking


    【解决方案1】:

    您需要在您的应用中获取MulticastLock,这将允许您的应用接收未明确发送到网络上此设备的数据包。

    需要许可:

    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    

    示例代码:

    // Acquire multicast lock
    WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    MulticastLock multicastLock = wifi.createMulticastLock("multicastLock");
    multicastLock.setReferenceCounted(true);
    multicastLock.acquire();
    
    //Do some mutlicast job here
    ... ...
    
    // Once your finish using it, release multicast lock
    if (multicastLock != null) {
        multicastLock.release();
        multicastLock = null;
    }
    

    【讨论】:

    • 看起来这仅适用于 wifi 多播数据包。我正在通过互联网进行多播(使用普通 APN,没有 WIFI)。还能用吗?
    • 我认为在 Android 上是不可能的,看看回答 here 是否有帮助。
    • @ShashankKadne,我最近回顾了我的一个项目,它使用 JmDNS 进行一些多播操作。演示版自行发布模拟 mdns 服务并在设备上检测。我实际上忘记了我曾经在3G网络下多次测试和运行它。我只是仔细检查了行为,我现在可以确认WifiManager.MulticastLock 在 3G 网络下工作(无论 WIFI 是否打开/关闭,状态栏中的 3G 处于活动状态)。请尝试一下,让我知道这是否也适用于您。
    • 如您所见,我的演示应用程序在同一网络(无论是 3G 还是 WIFI)中自行创建和检测模拟 mdns 服务。在您的情况下,如果 mdns 数据包(例如从另一个网络提出)在您的手机网络中是可访问的(可能需要一些路由),它应该可以按预期工作。
    • (+1)谢谢@yorkw。我会尽力让你知道的。
    【解决方案2】:

    android 中的 IPv4 多播支持实施得很差。仍然存在纸杯蛋糕时代的错误。

    我在做一个依赖 mDNS/多播进行服务发现的项目时遇到了类似的问题。我的 Android 应用程序根本不会订阅多播组。我通过在 Ubuntu 14.04 机器上创建便携式访问点并在其上运行 tcpdump 来验证这一点。连接到它的 Android 设备根本不会发出加入组所需的 IGMP 消息。我可以发送数据包但不能接收它们。

    我注意到,每当我加入网络时,我都会收到一条 IPv6 加入组消息给所有系统。这促使我尝试使用 IPv6 多播地址,并且成功了。

    较新的 android 设备支持 IPv6,它具有内置和强制多播支持。因此,不要使用 4 类 IPv4 多播地址,而是修改您的代码以使用 IPv6 地址。这将使您的代码至少在本地级别上工作。

    http://developer.android.com/reference/java/net/Inet6Address.html

    此页面包含大量有关根据您的需要使用哪个 IP 的信息。

    有人说它可以在没有 WiFiManager.crrateMulticastLock() 的情况下工作,但我没有尝试过。

    理论上,多播到全球网络当然是可能的。但我从未见过一个成功的实际实施。鉴于无处不在的深奥的路由器和防火墙。

    这个 SO 问题显示了它是如何在桌面上完成的。类似的代码也适用于 android。

    IPv6 Multicast example

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-15
      • 1970-01-01
      • 2017-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-09
      相关资源
      最近更新 更多