Why does multicast reception not work on some Andr

2019-02-06 18:45发布

问题:

It seems multicast reception does not work on some Android devices. I can not receive multicast with 4 out of 13 test devices. On those 4 devices it seems the app does not send the IGMP request to join the multicast group.

The code to receive the multicast looks like so:

WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
WifiManager.WifiLock wifiLock = wifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, TAG);
WifiManager.MulticastLock multicastLock = wifiManager.createMulticastLock(TAG);
multicastLock.setReferenceCounted(true);

wifiLock.acquire();
multicastLock.acquire();

try {
    MulticastSocket socket = new MulticastSocket(32123);

    InetAddress group = InetAddress.getByName("224.1.2.3");
    socket.joinGroup(group);

    DatagramPacket packet;
    byte[] buf = new byte[256];
    packet = new DatagramPacket(buf, buf.length);

    socket.receive(packet);

    socket.leaveGroup(group);
    socket.close();
} catch (IOException e) {
    e.printStackTrace();
}

multicastLock.release();
wifiLock.release();

The app has the following permissions:

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

To demonstrate the problem I created a little test project using the above code on GitHub: MulticastTest.

Is there a problem with my code? Do I miss a permission?

EDIT 1: This problem does not seem to relate to a specific Android version. I can reproduce the behaviour on Android 4.x, 5.x, and 6.x.

EDIT 2: There is a related question.

回答1:

Bad news: This seems to be related to the affected devices. There is no /proc/net/igmp available exactly on those devices that can not receive the multicast traffic. As already expected this very likely leads to the missing join group request (IP_ADD_MEMBERSHIP).

We tried with the Android Java API, BSD sockets, and Boost.Asio. Same result with all three options.

We verified the problem with an app called Multicast Tester. This app has the same problem on the same devices as our app. No IGMP request is send by the device and of course no multicast traffic is received.

There are some open and closed (with statuses Obsolete and WrongForum) issues in the Android issue tracker. I think the closed issues are marked as Obsolete/WrongForum because it is not a problem in Android but specific to the affected devices (setup).

It seems the kernel on the affected devices was built with

CONFIG_IP_MULTICAST=n

in the kernel configuration file. That's also why /proc/net/igmp is not available on the affected devices. It obviously is only created when CONFIG_IP_MULTICAST is set as can be seen in the Linux kernel code.