同一主机上的应用程序之间的多播

Multicast between applications on the same host

根据我的阅读,同一主机上的两个应用程序应该能够通过多播发送和接收数据报。我试图使用以下 Java 代码(这是 Javadoc for MulticastSocket 中给出的内容的稍微修改版本)来实现这一点:

    public static void main(String[] args) throws IOException{

        NetworkInterface nic = NetworkInterface.getByName("wlan4");

        int port = 6789;
        InetAddress group = InetAddress.getByName("228.5.6.7");
        MulticastSocket s = new MulticastSocket(port);
        s.setNetworkInterface(nic);
        s.joinGroup(group);

        if(args.length > 0 && args[0].equals("send")){
            System.out.println("SEND MODE");
            String msg = "Hello";
            DatagramPacket hi = new DatagramPacket(msg.getBytes(), msg.length(),
                                    group, port);
            s.send(hi);
        }else{

            byte[] buf = new byte[1000];
            DatagramPacket recv = new DatagramPacket(buf, buf.length);

            System.out.println("RECEIVE MODE");
            s.receive(recv);
            System.out.println(MessageFormat.format("Received: {0}",
                new String(recv.getData()).trim()));

            s.leaveGroup(group);
        }
    }

如果我 运行 上面的代码,将 send 作为输入参数,程序执行得很好,它发送数据包然后终止。但是,如果我想接收数据包,程序会被接收方法阻塞,因为它永远不会接收到数据报。我通过 运行 在我的机器上使用多个应用程序实例测试了这一点,包括一个和多个接收者以及一个发送者。 Non 随时收到任何消息。

另一方面,如果我让应用程序接收它刚刚发送的内容(通过 运行无条件地接收应用程序是否正在发送的方法),它仅对该应用程序有效。这使我相信 JVM 实例在该套接字上具有独占绑定,不允许其他人使用它(即使选项 getReuseAddress() returns 对 MulticastSockets 为真)。

我 运行正在 Windows 10 下,并且已经验证 UDP 数据包是使用 Wireshark 发送到网络的,所以我认为这与数据包不是交付给两个应用程序。

我该怎么做才能允许两个应用程序在同一端口号上通过多播进行通信?

编辑:

总体思路是服务器向所选网络上的所有侦听客户端发送数据报(因此示例中将 NIC 指定为 "wlan4" 的原因),而不管它们在何处执行(例如是否与服务器在同一主机上)。

经过一些调试,我意识到如果应用程序本身正在发送 接收多播数据报,我可以从多个应用程序接收多播数据包。事实证明,向多播组发送数据包会以某种方式触发此功能。这对我来说似乎是一个错误。

但是,为了让上面的示例按预期工作,我不得不将第一个数据报发送(并丢弃)到多播通道。我以最简单的方式做到了这一点,将 else 块更改为以下内容:

        byte[] buf = new byte[1000];
        DatagramPacket recv = new DatagramPacket(buf, buf.length);
        s.send(new DatagramPacket("A".getBytes(), 1, group, port));
        s.receive(recv);

        System.out.println("RECEIVE MODE");
        s.receive(recv);
        System.out.println(MessageFormat.format("Received: {0}",
                new String(recv.getData()).trim()));

        s.leaveGroup(group);