Почему многоадресный прием не работает на некоторых устройствах Android?
Похоже, многоадресный прием не работает на некоторых устройствах Android. Я не могу получить многоадресную рассылку с 4 из 13 тестовых устройств. Похоже, что на этих 4 устройствах приложение не отправляет IGMP-запрос на присоединение к многоадресной группе.
Код для получения многоадресной рассылки выглядит так:
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();
Приложение имеет следующие разрешения:
<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"/>
Чтобы продемонстрировать проблему, я создал небольшой тестовый проект с использованием приведенного выше кода на GitHub: MulticastTest.
Есть ли проблема с моим кодом? Я пропускаю разрешение?
РЕДАКТИРОВАТЬ 1: Эта проблема, похоже, не относится к конкретной версии Android. Я могу воспроизвести поведение на Android 4.x, 5.x и 6.x.
РЕДАКТИРОВАТЬ 2: Есть связанный вопрос.
1 ответ
Плохие новости: похоже, это связано с уязвимыми устройствами. Здесь нет /proc/net/igmp
доступно именно на тех устройствах, которые не могут принимать многоадресный трафик. Как уже ожидалось, это очень вероятно приводит к отсутствию запроса группы присоединения (IP_ADD_MEMBERSHIP
).
Мы пробовали использовать Android API Java, сокеты BSD и Boost.Asio. Тот же результат со всеми тремя вариантами.
Мы проверили проблему с приложением под названием Multicast Tester. Это приложение имеет ту же проблему на тех же устройствах, что и наше приложение. IGMP-запрос не отправляется устройством и, конечно, многоадресный трафик не принимается.
В трекере проблем Android есть некоторые открытые и закрытые (со статусами устаревшие и WrongForum) проблемы. Я думаю, что закрытые проблемы помечены как устаревшие /WrongForum, потому что это не проблема в Android, а специфическая для уязвимых устройств (настройка).
Кажется, ядро на затронутых устройствах было собрано с
CONFIG_IP_MULTICAST=n
в файле конфигурации ядра. Вот почему /proc/net/igmp
недоступно на затронутых устройствах. Очевидно, он создается только тогда, когда CONFIG_IP_MULTICAST
устанавливается, как видно из кода ядра Linux.