9

我正在开发一个聊天应用程序,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

任何帮助将不胜感激。

4

2 回答 2

13

您需要在您的应用程序中获取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;
}
于 2012-11-04T21:17:23.817 回答
5

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

我遇到了一个类似的问题,我正在做一个依赖 mDNS/multicast 进行服务发现的项目。我的 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 question 显示了它是如何在桌面上完成的。类似的代码也适用于 android。

IPv6 组播示例

于 2016-03-23T15:35:54.117 回答