java Android 设备收不到多播包

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13221736/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 11:55:55  来源:igfitidea点击:

Android device not receiving multicast package

javaandroidnetworking

提问by Shashank Kadne

I am developing a chat application where Android clients will exchange their IP's using multicasting(UDP).

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

Every device will send its ip to multiple clients(all the devices running this app) in one separate Thread. There will be another receiver thread which will listen to these multicast packets. Here is my code.

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

//Multicasting code.

//多播代码。

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

//Receiver code

//接收方代码

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

The problem is every device prints its own address. It seems it never listens to other multicast packages(I mean it should print other ip's as well). I also get a below log, not sure if that's related.

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

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

Any help will be appreciated.

任何帮助将不胜感激。

回答by yorkw

You need acquire a MulticastLockin your app, which will allow your app receive packets that are not explicitly addressed to this device on the network.

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

Permission required:

需要的权限:

<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"/>

Sample code:

示例代码:

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

回答by agathver

IPv4 multicast support in android is poorely implemented. There are bugs from cupcake era still present.

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

I ran into a similar problem I was doing a project that relied on mDNS/multicast for service discovery. My Android app would simply not subscribe to the multicast group. I verified this by creating a portable access point on a Ubuntu 14.04 machine and running tcpdump on it. Android devices connected to it simply didn't emit IGMP messages required for joining a group. I could send packets but not receive them.

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

What I noticed that I was getting an IPv6 join group message to all-systems whenever I joined the networked. This prompted me to try a IPv6 multicast address and that worked.

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

Newer android devices support IPv6, which has built-in and mandatory multicast support. So instead of using an Class 4 IPv4 multicast address, modify your code to use an IPv6 address. This will make your code to work on at least the local level.

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

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

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

This page has a wealth of information about which IP to use as per your needs.

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

Some say that it works without the WiFiManager.crrateMulticastLock() but I didn't try that.

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

Multicasting to global networks is certainly possible theoretically. But I've never seen a successful practical implementation of one. Given the esoteric routers and firewalls that exist all around.

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

This SO question shows how it is done on desktop. Similar code also works with android.

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

IPv6 Multicast example

IPv6 组播示例