MulticastSocket 未在任何本地主机客户端上接收到多播数据包

Multicast packet not received by MulticastSocket on any localhost client

简介

有很多关于创建多播发布者和接收者的教程。

我使用找到的 here 并稍作修改。

其他几个:

请注意,这些教程都非常相似。

详情:

服务器 运行 在端口 7777 上并将数据报发送到 224.0.0.0(我测试了多播范围内的其他几个 IP:224.0.0.0239.255.255.255,但这些都不起作用)

客户端然后加入多播组224.0.0.0并等待数据包响应(运行作为线程)

extra: 我发送这样的消息:123.23.13.12[host-name]:1234 作为数据报数据。

问题:

来自服务器(在本地主机上)的多播数据包未到达客户端(在本地主机上)。

客户端包括 java 控制台应用程序(代码见下方)和 Android 模拟器上的 Android 应用程序。两个客户端都没有收到多播数据包。

我知道正在发送多播数据包,如 Wireshark

中所示

下面是我所拥有的一个基本示例。

TL;DR: 服务器发送多播数据包(通过 Wireshark 确认)但客户端没有收到。

非常欢迎提出建议!

更新

根据 Just another Java programmer 的评论,我检查了我的防火墙。你瞧,我的防火墙在 inputforward 链上掉线了。我将其设置为 accept所有传入(暂时)

基于 Ron Maupin 的评论。

应用这些更改后,客户端仍然收不到任何数据包。

代码:

服务器端(控制台应用程序):

String multicastAddress = "239.254.0.0", multicastPort = 7777;

private void broadcastServer() {
    String message = null;
    MulticastSocket s = null;
    InetAddress local = null, group = null;
    InetAddress[] allByName;
    try {
        local = InetAddress.getLocalHost();
        s = new MulticastSocket(multicastPort);
        s.setReuseAddress(true);
        s.setInterface(local)
        s.joinGroup(InetAddress.getByName(multicastAddress));
        group = InetAddress.getByName(multicastAddress);
    } catch (SocketException e) {
        e.printStackTrace();
    } catch (UnknownHostException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    MulticastSocket socket = s;

    // getNetworkIP() gets lan network ip
    // serverport = 1025
    message = local.getHostAddress() + ":" + String.valueOf(serverPort);
    byte[] buf = message.getBytes();
    DatagramPacket packet = new DatagramPacket(buf, buf.length, group, multicastPort);

    thdBroadcaster = new Thread(() -> {
        while (bRunServer) {
            try {
                Thread.sleep(1000);
                printf("[Broadcast] Broadcasting...");
                socket.send(packet);
                printf("OK\n");
                printf("");
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        socket.close();
    });
    thdBroadcaster.start();
}

客户端(控制台应用程序):

String multicastAddress = "239.254.0.0", multicastPort = 7777;

private void startServerListenerThread() {
    Thread thdServerListener = new Thread(new Runnable() {
        @Override
        public void run() {
            MulticastSocket socket = null;
            InetAddress group = null;
            try {
                socket = new MulticastSocket(multicastPort);
                socket.setReuseAddress(true);
                group = InetAddress.getByName(multicastAddress);
                socket.joinGroup(group);

                handleServerBroadcasts(socket);
                socket.leaveGroup(group);
                socket.close();

            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        private void handleServerBroadcasts(final MulticastSocket socket) {
            while (true){
                try {
                    byte[] buf = new byte[256];
                    DatagramPacket packet = new DatagramPacket(buf, buf.length);
                    socket.receive(packet);
                    String received = new String(packet.getData());

                    String address = received.substring(0, received.indexOf(":"));
                    String port = received.substring(received.indexOf(":") + 1);

                    System.out.println();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (Exception x){
                    x.printStackTrace();
                }
            }
        }
    });
    thdServerListener.start();
}

解决方案最终只是一个微不足道的改动。

解决问题很简单,只需更改:

s = new MulticastSocket(multicastPort);

s = new MulticastSocket();

仅在服务器端

注意:需要防火墙,检查是否允许多播数据包通过。我使用的接口是本地主机,但这不是必需的。不过这可以通过获取你需要的指定接口来设置。

更新

EJP 的评论:

我将使用的端口更改为8888。此端口用于发送服务器数据报和客户端连接他们的 MulticastSocket

您正在调用 setReuseAddress() 绑定套接字。它没有效果。您需要创建一个未绑定的 MulticastSocket,调用 setReuseAddress(),然后绑定它。