4

这是在 Java 中,但如果需要,我总是可以通过 JNI 恢复为 C。

我有一个带有两个 NIC 的系统,每个 NIC 都连接到一个不同的子网。我想使用多播(特别是 SDP)来发现两个网络上的其他主机。

一个网络很简单:在指定的端口上创建一个 MulticastSocket,将它加入组,然后我得到数据包。简单。

两个网络:到目前为止不可能。我试过了:

1) 创建两个套接字,绑定到同一个端口并使用 setInterface() 或 setNetworkInterface() “连接”到正确的接口。没有运气,即使在 setReuseAddress() 的各种排列之后。

2) 创建一个套接字,然后尝试加入两次,两次调用 joinGroup(SocketAddress mcastaddr, NetworkInterface netIf)。第二次加入呼叫失败。

Java 之外的解决方案会很棒。特别是,如果我可以设置有效“组合”两个接口的多播路由(然后我可以查看每个数据包以确定哪个网络),那就没问题了。正如我之前提到的,任何数量的本机代码都可以在这个环境中使用(Linux,带有 Apache “luni” java 基础设施)。

谢谢!

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

我在这里没有合理的设置来尝试这个,但是接收多播消息不应该要求 MulticastSocket 绑定到来自多播地址的端口号,并且 setNetworkInterface 用于设置用于出站消息的接口。

我会尝试创建两个不同的 MulticastSockets(在任何空闲端口上),然后使用 joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) 在它们上使用相同的多播地址,但使用不同的网络接口。

于 2010-01-10T17:15:12.577 回答
0

您是否考虑过为此使用 ZeroConf?

jmdns 项目有一个纯 java 实现,应该可以很好地工作。

于 2010-01-10T17:17:02.397 回答