Skip to content

Netty UDP multicast using Epoll throws Exception while joining multicast group #10995

@globdan

Description

@globdan

Expected behavior

Joining multicast group on given port

Actual behavior

Throws Exception:

Exception in thread "main" io.netty.channel.ChannelException: setsockopt() failed: Invalid argument
	at io.netty.channel.epoll.LinuxSocket.joinGroup(Native Method)
	at io.netty.channel.epoll.LinuxSocket.joinGroup(LinuxSocket.java:124)
	at io.netty.channel.epoll.EpollDatagramChannel.joinGroup(EpollDatagramChannel.java:172)
	at io.netty.channel.epoll.EpollDatagramChannel.joinGroup(EpollDatagramChannel.java:154)
	at io.netty.channel.epoll.EpollDatagramChannel.joinGroup(EpollDatagramChannel.java:147)
	at trading.app.udp.UDPEpollListener.run(UDPEpollListener.java:56)
	at trading.app.udp.UDPEpollListener.main(UDPEpollListener.java:33)

After changing all Epoll classes to NIO the code runs without any problem.

Steps to reproduce

Run the given code

Minimal yet complete reproducer code (or URL to code)

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.epoll.EpollDatagramChannel;
import io.netty.channel.epoll.EpollEventLoopGroup;
import lombok.val;

import java.net.Inet6Address;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketException;

public class UDPEpollListener {
    private final NetworkInterface networkInterface;
    private final Inet6Address networkInterfaceAddress;
    private int socketBufferSize;
    private String multicastGroupIpv4Address;
    private int multicastGroupPort;

    public UDPEpollListener(String networkInterfaceName, int socketBufferSize, String multicastGroupIpv4Address, int multicastGroupPort) {
        this.networkInterface = getNetworkInterface(networkInterfaceName);
        this.networkInterfaceAddress = getLocalAddress(this.networkInterface);
        this.socketBufferSize = socketBufferSize;
        this.multicastGroupIpv4Address = multicastGroupIpv4Address;
        this.multicastGroupPort = multicastGroupPort;
    }

    public static void main(String[] args) {
        val listener = new UDPEpollListener("enp0s3", 16777216, "233.96.6.2", 23455);
        try {
            listener.run();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void run() throws InterruptedException {
        Bootstrap bootstrap = new Bootstrap();
        bootstrap
                .group(new EpollEventLoopGroup())
                .channel(EpollDatagramChannel.class)
                .option(ChannelOption.SO_REUSEADDR, true)
                .option(ChannelOption.IP_MULTICAST_IF, this.networkInterface)
                .option(ChannelOption.SO_RCVBUF, this.socketBufferSize)
                .localAddress(this.networkInterfaceAddress, multicastGroupPort)
                .handler(new ChannelInitializer<EpollDatagramChannel>() {
                    @Override
                    protected void initChannel(EpollDatagramChannel datagramChannel) {
                        datagramChannel.pipeline().addLast(new MulticastHandler());
                    }
                });
        EpollDatagramChannel channel = (EpollDatagramChannel) bootstrap.bind(multicastGroupPort).sync().channel();
        InetSocketAddress multicastSocketAddress = new InetSocketAddress(multicastGroupIpv4Address, multicastGroupPort);
        ChannelFuture channelFuture = channel.joinGroup(multicastSocketAddress, this.networkInterface).sync();
        channelFuture.addListener((ChannelFutureListener) listener -> {
            if (channelFuture.isSuccess()) {
                System.out.println("Working...");
            }});
    }

    private NetworkInterface getNetworkInterface(String networkInterfaceName) {
        try {
            return NetworkInterface.getByName(networkInterfaceName);
        } catch (SocketException e) {
            throw new RuntimeException();
        }
    }

    private Inet6Address getLocalAddress(NetworkInterface networkInterface) {
        val addresses = networkInterface.getInetAddresses();
        while (addresses.hasMoreElements()) {
            val address = addresses.nextElement();
            if (address instanceof Inet6Address) {
                return (Inet6Address) address;
            }
        }
        throw new RuntimeException();
    }
}

Netty version

4.1.58.Final

JVM version (e.g. java -version)

openjdk version "15.0.2" 2021-01-19
OpenJDK Runtime Environment (build 15.0.2+7-27)
OpenJDK 64-Bit Server VM (build 15.0.2+7-27, mixed mode, sharing)

OS version (e.g. uname -a)

Linux centos.dev 4.18.0-240.10.1.el8_3.x86_64 #1 SMP Mon Jan 18 17:05:51 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions