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

发布于 2024-08-17 17:54:38 字数 579 浏览 6 评论 0原文

这是用 Java 编写的,但如果需要,我总是可以通过 JNI 恢复到 C。

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

一个网络很简单:在指定端口上创建一个 MulticastSocket,将其加入组,然后我就可以获取数据包。简单。

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

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

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

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

谢谢!

This is in Java, but I can always revert to C via JNI if needed.

I have a system with two NICs, each connected to a distinct subnet. I want to use multicast (in particular, SDP) to discover other hosts on both networks.

One network is easy: create a MulticastSocket on the specified port, joinGroup it, and I get packets. Simplicity.

Two networks: so far impossible. I've tried:

1) creating two sockets, binding to the same port and using setInterface() or setNetworkInterface() to "connect" to the right interface. No luck, even after various permutations of setReuseAddress().

2) create a single socket, and then attempt to join twice, with two calls to joinGroup(SocketAddress mcastaddr, NetworkInterface netIf). The second join call fails.

Solutions outside of Java would be great. In particular, if I could set up multicast routes that would effectively 'combine' the two interfaces (I could then look at each packet to determine which network) that would be fine. As I mentioned before, any amount of native code is usable in this environment (Linux, with the Apache "luni" java infrastructure).

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

入怼 2024-08-24 17:54:38

巧合的是,我最近也在研究类似的问题。

下面是一些 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);
    }
}

Coincidentally, I was working on a similar problem recently.

Here's some Java code which does what you want -- it picks up SDP packets on several interfaces. joinGroup is used to "attach" to the specified interfaces.

/**
 * 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);
    }
}
无所谓啦 2024-08-24 17:54:38

我建议使用 JGroups,如果我正确理解您的需求,它会抽象您尝试执行的所有操作。它是一个优雅且制作精良的多播框架(以及类似多播的语义,必要时进行模拟)。

I'd recommend using JGroups, which abstracts everything you're trying to do, if I understand your needs correctly. it's an elegant and well-made framework for multicast (and multicast-like semantics, emulated when necessary).

沫离伤花 2024-08-24 17:54:38

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

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

I have no reasonable setup to try this here, but receiving multicast messages should not require the MulticastSocket to be bound to the port number from the multicast address and setNetworkInterface is used to set the interface used for outbound messages.

What I would try to create two different MulticastSockets (on any free port) and then use joinGroup(SocketAddress mcastaddr, NetworkInterface netIf) on each of them using the same multicast address, but different network interfaces.

北风几吹夏 2024-08-24 17:54:38

您是否考虑过使用 ZeroConf 来实现此目的?

jmdns 项目有一个纯 java 实现,应该运行得很好。

Have you considered using ZeroConf for this?

The jmdns project has a pure java implementation which should work very well.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文