Nullpointer exception when trying to receive UDP multicast

只愿长相守 提交于 2021-02-09 07:01:38

问题


i'm puzzeled after a few attempts to get a simple UDP multicast receiver working. After my own code did not work as expected i tried out the exact example posted in the vertx documentation:

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 (e.g. 192.168.178.52) instead of 0.0.0.0. However, this means iterating over all network interfaces and adding a socket per interface.

Any ideas? Thank you!


回答1:


UDP multicast listening is incredibly error prone, especially in virtual machines.

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.



来源:https://stackoverflow.com/questions/49449129/nullpointer-exception-when-trying-to-receive-udp-multicast

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!