首页 文章

如何在多宿主系统上使用多播(Java,Linux)

提问于
浏览
4

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

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

一个网络很简单:在指定端口上创建MulticastSocket,joinGroup它,我得到数据包 . 简单 .

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

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

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

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

谢谢!

4 回答

  • 2

    巧合的是,我最近正在研究类似的问题 .

    这里有一些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);
        }
    }
    
  • 0

    我建议使用JGroups,它将您所有的东西抽象为一个优雅且制作精良的多播框架(以及类似于多播的语义,必要时进行模拟) .

  • 0

    我没有合理的设置来尝试这一点,但接收多播消息不应要求MulticastSocket绑定到多播地址的端口号,setNetworkInterface用于设置用于出站消息的接口 .

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

  • 7

    您是否考虑过使用ZeroConf?

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

相关问题