'Netty shutdown/Stop UDP server

I'm trying to create Netty UDP listener. The problem I faced is that I can't stop udp server like tcp, the udp always is running, even with shutdowngracefully called, the only way to stop it is by throwing exception.

private int port;
private UDPViewModel viewModel;
private DefaultEventLoopGroup defaultEventLoopGroup;

public UdpServer(UDPViewModel viewModel, int port) {
   this.port = port;
   this.viewModel = viewModel;
}

@Override
public void run() {
    defaultEventLoopGroup = new DefaultEventLoopGroup();
    try {

        ServerBootstrap bootstrap = new ServerBootstrap()
                .channel(UdpServerChannel.class)
                .group(defaultEventLoopGroup)
                .childHandler(new ChannelInitializer<Channel>() {
                    @Override
                    protected void initChannel(Channel channel) {
                        channel.pipeline()
                                .addLast(new ReadTimeoutHandler(5))
                                .addLast(new UdpServerHandler(viewModel));
                    }
                });
        bootstrap.bind(port).sync().channel().closeFuture().syncUninterruptibly().await();

        System.out.println("UDP Server : [successfully started]");
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        defaultEventLoopGroup.shutdownGracefully();
    }
}

Anyone has any ideas on how to shutdown netty udp server properly ?



Solution 1:[1]

First things first, I'm assuming you use this git repo which by the way is pretty poorly written. Furthermore I would recommend to not use it since UDP isn't intended to be used in a server/client model and all that repo does is manage your UDP channels which are not existent since UDP is connectionless. All it really does is to store a fake channel instance which in its core is just a InetAddress. What you could do instead is to use a normal thread safe List or somesorte of Storage for the different InetAddress you wanna cache and just use this.

But if you really need to use this repo you need to stop the ServerChannel instance since the UdpServerChannel starts a new eventloop which isn't exposed to the outside and can only be stopped when closing the channel. (This is another reason you shouldn't use it, it's wasteful to open multiple EventLoopGroups for the same thing)

Solution 2:[2]

I guess I founded another way to solve this. A solution to my problem, It's not PERFECT but it does what I want.

public class UdpServer {

private int port;
private UDPViewModel viewModel;
private final EventLoopGroup nioEventLoopGroup;
private ChannelFuture channelFuture;

public UdpServer(UDPViewModel viewModel, int port) {
   this.port = port;
   this.viewModel = viewModel;
    nioEventLoopGroup = new NioEventLoopGroup();
}

public void run() {
    System.out.println("UDP Server is starting.");
    try{
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(nioEventLoopGroup)
                .channel(NioDatagramChannel.class)
                .handler(new ChannelInitializer<Channel>() {
                    @Override
                    protected void initChannel(Channel channel) {
                        channel.pipeline().addLast(
                                new LoggingHandler(LogLevel.INFO),
                                new StringEncoder(), new StringDecoder());
                        channel.pipeline().addLast(
                                new UdpServerHandler(viewModel));
                    }
                });
        channelFuture = bootstrap.bind(port).sync();

    }
    catch (InterruptedException e) {
        System.err.println("UDP listener was interrupted and shutted down");
        e.getCause();
    }
}

public void StopServer()
{
    try {
        nioEventLoopGroup.shutdownGracefully().sync();
        channelFuture.channel().closeFuture().sync();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
}

Solution 3:[3]

close it in the UdpServerHandler

notice

public void channelRead0(ChannelHandlerContext ctx, DatagramPacket packet)

call ctx.close()

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ingrim4
Solution 2 MINIKAS
Solution 3 zhao