9

Android クライアントがマルチキャスト (UDP) を使用して IP を交換するチャット アプリケーションを開発しています。

すべてのデバイスは、1 つの個別のスレッドで複数のクライアント (このアプリを実行しているすべてのデバイス) にその 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/マルチキャストに依存するプロジェクトを行っていたときに、同様の問題に遭遇しました。私の Android アプリは、マルチキャスト グループにサブスクライブしません。これを確認するには、Ubuntu 14.04 マシンでポータブル アクセス ポイントを作成し、tcpdump を実行しました。それに接続された Android デバイスは、グループに参加するために必要な IGMP メッセージを送信しませんでした。パケットを送信できましたが、受信できませんでした。

ネットワークに参加するたびに、すべてのシステムに IPv6 参加グループ メッセージが表示されることに気付きました。これにより、IPv6 マルチキャスト アドレスを試すようになりましたが、うまくいきました。

新しい Android デバイスは IPv6 をサポートしており、IPv6 には必須のマルチキャスト サポートが組み込まれています。したがって、クラス 4 IPv4 マルチキャスト アドレスを使用する代わりに、IPv6 アドレスを使用するようにコードを変更してください。これにより、コードが少なくともローカル レベルで機能するようになります。

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

このページには、ニーズに応じて使用する IP に関する豊富な情報があります。

WiFiManager.crrateMulticastLock() がなくても機能すると言う人もいますが、私はそれを試しませんでした。

グローバル ネットワークへのマルチキャストは、理論的には確かに可能です。しかし、実用化に成功した例は見たことがありません。いたるところに存在する難解なルーターとファイアウォールを考えると。

This SO question は、デスクトップでどのように行われるかを示しています。同様のコードは Android でも機能します。

IPv6 マルチキャストの例

于 2016-03-23T15:35:54.117 に答える