4

これは Java ですが、必要に応じて JNI 経由でいつでも C に戻すことができます。

2 つの NIC を備えたシステムがあり、それぞれが別個のサブネットに接続されています。マルチキャスト (特に SD​​P) を使用して、両方のネットワーク上の他のホストを検出したいと考えています。

1 つのネットワークは簡単です。指定されたポートで MulticastSocket を作成し、それを joinGroup にすると、パケットが取得されます。シンプルさ。

2 つのネットワーク: これまでのところ不可能です。私はもう試した:

1) 2 つのソケットを作成し、同じポートにバインドし、setInterface() または setNetworkInterface() を使用して正しいインターフェースに「接続」します。setReuseAddress() のさまざまな順列の後でも、うまくいきません。

2) 1 つのソケットを作成し、joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) を 2 回呼び出して、2 回参加を試みます。2 番目の参加呼び出しは失敗します。

Java以外のソリューションは素晴らしいでしょう。特に、2 つのインターフェイスを効果的に「結合」するマルチキャスト ルートを設定できれば (その後、各パケットを調べてどのネットワークかを判断できます)、それで問題ありません。前に述べたように、この環境 (Apache "luni" Java インフラストラクチャを備えた Linux) では、任意の量のネイティブ コードを使用できます。

ありがとう!

4

4 に答える 4

8

偶然にも、私は最近同様の問題に取り組んでいました。

これがあなたが望むことをするいくつかのJavaコードです-それはいくつかのインターフェースでSDPパケットを拾います。joinGroupは、指定されたインターフェイスに「接続」するために使用されます。

/**
 * Demonstrate multi-homed multicast listening
 *
 * usage: java Multihome eth0 eth1 lo <etc>
 */

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.MulticastSocket;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;

public class Multihome {
    // SDP constants
    public static final String MULTICAST_ADDRESS = "239.255.255.250";
    public static final int MULTICAST_PORT = 1900;

    // args: each arg is the name of an interface.
    public void doMain(Set<String> args)
            throws Exception
    {
        InetSocketAddress socketAddress =
                new InetSocketAddress(MULTICAST_ADDRESS, MULTICAST_PORT);
        MulticastSocket socket = new MulticastSocket(MULTICAST_PORT);
        Enumeration<NetworkInterface> ifs =
                NetworkInterface.getNetworkInterfaces();

        while (ifs.hasMoreElements()) {
            NetworkInterface xface = ifs.nextElement();
            Enumeration<InetAddress> addrs = xface.getInetAddresses();
            String name = xface.getName();

            while (addrs.hasMoreElements()) {
                InetAddress addr = addrs.nextElement();

                System.out.println(name + " ... has addr " + addr);
            }

            if (args.contains(name)) {
                System.out.println("Adding " + name + " to our interface set");
                socket.joinGroup(socketAddress, xface);
            }
        }

        byte[] buffer = new byte[1500];
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

        while (true) {
            try {
                packet.setData(buffer, 0, buffer.length);
                socket.receive(packet);
                System.out.println("Received pkt from " + packet.getAddress() +
                                   " of length " + packet.getLength());
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    public static void main(String[] args)
            throws Exception
    {
        Set<String> argSet = new HashSet<String>();
        Multihome multi = new Multihome();

        for (String arg : args) {
            argSet.add(arg);
        }

        multi.doMain(argSet);
    }
}
于 2010-03-04T21:30:50.543 に答える
2

あなたのニーズを正しく理解していれば、あなたがやろうとしていることすべてを抽象化するJGroupsを使用することをお勧めします。これは、マルチキャスト (および必要に応じてエミュレートされるマルチキャストのようなセマンティクス) のためのエレガントでよくできたフレームワークです。

于 2010-01-10T17:43:35.517 に答える
0

これに ZeroConf を使用することを検討しましたか?

jmdns プロジェクトには、非常にうまく機能する純粋な Java 実装があります。

于 2010-01-10T17:17:02.397 に答える
0

ここでこれを試すための合理的な設定はありませんが、マルチキャスト メッセージを受信するために MulticastSocket をマルチキャスト アドレスからのポート番号にバインドする必要はなく、アウトバウンドメッセージに使用されるインターフェイスを設定するために setNetworkInterface が使用されます。

2 つの異なる MulticastSockets (空きポート) を作成し、同じマルチキャスト アドレスを使用してそれぞれで joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) を使用しますが、ネットワーク インターフェイスは異なります。

于 2010-01-10T17:15:12.577 に答える