【问题标题】:Nullpointer exception when trying to receive UDP multicast尝试接收 UDP 多播时出现 Nullpointer 异常
【发布时间】:2018-03-23 11:54:31
【问题描述】:

在尝试让一个简单的 UDP 多播接收器正常工作后,我感到很困惑。 在我自己的代码没有按预期工作后,我尝试了 vertx 文档中发布的确切示例:

DatagramSocket socket = vertx.createDatagramSocket(new DatagramSocketOptions());
socket.listen(1234, "0.0.0.0", asyncResult -> {
  if (asyncResult.succeeded()) {
    socket.handler(packet -> {
      // Do something with the packet
    });

    // join the multicast group
    socket.listenMulticastGroup("230.0.0.1", asyncResult2 -> {
        System.out.println("Listen succeeded? " + asyncResult2.succeeded());
    });
  } else {
    System.out.println("Listen failed" + asyncResult.cause());
  }
});

执行后出现如下异常:

java.lang.NullPointerException: networkInterface
    at io.netty.channel.socket.nio.NioDatagramChannel.joinGroup(NioDatagramChannel.java:409)
    at io.netty.channel.socket.nio.NioDatagramChannel.joinGroup(NioDatagramChannel.java:368)
    at io.netty.channel.socket.nio.NioDatagramChannel.joinGroup(NioDatagramChannel.java:362)
    at io.vertx.core.datagram.impl.DatagramSocketImpl.listenMulticastGroup(DatagramSocketImpl.java:90)

当提供正确的网络接口 IP 地址(例如 192.168.178.52)而不是 0.0.0.0 时,我可以让它工作。但是,这意味着遍历所有网络接口并为每个接口添加一个套接字。

有什么想法吗?谢谢!

【问题讨论】:

  • 初始化过程中出现问题,您需要仔细调试它。可能NetworkInterface.getByInetAddress(localAddress().getAddress()) 是问题

标签: java udp multicast vert.x


【解决方案1】:

UDP 多播侦听极易出错,尤其是在虚拟机中。

这是来自我的生产代码。首先,要获得一个有效的接口:

static NetworkInterface mainInterface() throws SocketException {
    final ArrayList<NetworkInterface> interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
    final NetworkInterface networkInterface = interfaces.stream().filter(ni -> {
        boolean isLoopback = false;
        boolean supportsMulticast = false;
        boolean isVirtualbox = false;
        try {
            isLoopback = ni.isLoopback();
            supportsMulticast = ni.supportsMulticast();
            isVirtualbox = ni.getDisplayName().contains("VirtualBox") || ni.getDisplayName().contains("Host-Only");
        } catch (IOException loopbackTestFailure) {
        }
        final boolean hasIPv4 = ni.getInterfaceAddresses().stream().anyMatch(ia -> ia.getAddress() instanceof Inet4Address);
        return supportsMulticast && !isLoopback && !ni.isVirtual() && hasIPv4 && !isVirtualbox;
    }).sorted(Comparator.comparing(NetworkInterface::getName)).findFirst().orElse(null);
    return networkInterface;
}

然后,最安全的数据报套接字创建:

String multicastAddress = "230.0.0.1";
NetworkInterface networkInterface = mainInterface();
Future isListening = Future.future();
vertx.createDatagramSocket(new DatagramSocketOptions()
            .setReuseAddress(true)
            .setReusePort(true))
            .listen(6112, "0.0.0.0", next -> {
                next.result().listenMulticastGroup(multicastAddress, networkInterface.getName(), null, listener -> {
                    final DatagramSocket socket = listener.result();
                    socket.handler(packet -> {
                        // Your handler here
                    });

                    isListening.complete();
                });
            });

请注意我选择的高于 1024 的端口、重用标志以及 VirtualBox 的特殊外壳。

【讨论】:

  • 很好,谢谢!这与我最终得到的解决方案非常相似。除了迭代网络接口并整理出那些不起作用的接口之外,别无选择。
  • @DoctorPangloss 在调用listen() 时尝试使用0.0.0.0 之外的另一个地址绑定到数据报套接字,你有没有运气?到目前为止,多播仅适用于使用 0.0.0.0 的我,任何其他地址我只能接收单播 UDP,但不能接收多播。
猜你喜欢
  • 2015-04-16
  • 1970-01-01
  • 1970-01-01
  • 2015-02-05
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多