简体   繁体   English

尝试接收UDP多播时出现Nullpointer异常

[英]Nullpointer exception when trying to receive UDP multicast

i'm puzzeled after a few attempts to get a simple UDP multicast receiver working. 经过几次尝试让一个简单的UDP多播接收器正常工作后,我感到困惑。 After my own code did not work as expected i tried out the exact example posted in the vertx documentation: 在我自己的代码没有按预期工作后,我尝试了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());
  }
});

After executing, i got the following exception: 执行后,我得到以下异常:

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)

I can get it to work when providing the right IP address of the network interface (eg 192.168.178.52) instead of 0.0.0.0. 当提供网络接口的正确IP地址(例如192.168.178.52)而不是0.0.0.0时,我可以使它工作。 However, this means iterating over all network interfaces and adding a socket per interface. 但是,这意味着迭代所有网络接口并为每个接口添加套接字。

Any ideas? 有任何想法吗? Thank you! 谢谢!

UDP multicast listening is incredibly error prone, especially in virtual machines. UDP多播侦听非常容易出错,尤其是在虚拟机中。

This is from my production code. 这是我的生产代码。 First, to get a valid interface: 首先,获得一个有效的接口:

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;
}

Then, the most bullet-proof datagram socket creation: 然后,最防弹数据报套接字创建:

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();
                });
            });

Observe my choice of a higher-than-1024 port, the reuse flags, and the special casing for VirtualBox. 观察我选择的高于1024的端口,重用标志和VirtualBox的特殊外壳。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM