How to properly close a UDT server in Netty 4
- by Steffen
I'm trying to close my UDT server (Netty 4.0.5.Final) with shutDownGracefully() and reopen it on the same port. Unfortunately, I always get the socket exception below although it waits until the future has completed. I also added the socket option SO_REUSEADDR.
What is the proper way to do this?
Exception in thread "main" com.barchart.udt.ExceptionUDT: UDT Error : 5011 : another socket is already listening on the same UDP port : listen0:listen [id: 0x323d3939]
at com.barchart.udt.SocketUDT.listen0(Native Method)
at com.barchart.udt.SocketUDT.listen(SocketUDT.java:1136)
at com.barchart.udt.net.NetServerSocketUDT.bind(NetServerSocketUDT.java:66)
at io.netty.channel.udt.nio.NioUdtAcceptorChannel.doBind(NioUdtAcceptorChannel.java:71)
at io.netty.channel.AbstractChannel$AbstractUnsafe.bind(AbstractChannel.java:471)
at io.netty.channel.DefaultChannelPipeline$HeadHandler.bind(DefaultChannelPipeline.java:1006)
at io.netty.channel.DefaultChannelHandlerContext.invokeBind(DefaultChannelHandlerContext.java:504)
at io.netty.channel.DefaultChannelHandlerContext.bind(DefaultChannelHandlerContext.java:487)
at io.netty.channel.ChannelDuplexHandler.bind(ChannelDuplexHandler.java:38)
at io.netty.handler.logging.LoggingHandler.bind(LoggingHandler.java:254)
at io.netty.channel.DefaultChannelHandlerContext.invokeBind(DefaultChannelHandlerContext.java:504)
at io.netty.channel.DefaultChannelHandlerContext.bind(DefaultChannelHandlerContext.java:487)
at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:848)
at io.netty.channel.AbstractChannel.bind(AbstractChannel.java:193)
at io.netty.bootstrap.AbstractBootstrap$2.run(AbstractBootstrap.java:321)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:354)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:366)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:101)
at java.lang.Thread.run(Thread.java:724)
A small test program demonstration the problem:
public class MsgEchoServer {
public static class MsgEchoServerHandler extends ChannelInboundHandlerAdapter {
}
public void run() throws Exception {
final ThreadFactory acceptFactory = new UtilThreadFactory("accept");
final ThreadFactory connectFactory = new UtilThreadFactory("connect");
final NioEventLoopGroup acceptGroup = new NioEventLoopGroup(1,
acceptFactory, NioUdtProvider.MESSAGE_PROVIDER);
final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1,
connectFactory, NioUdtProvider.MESSAGE_PROVIDER);
try {
final ServerBootstrap boot = new ServerBootstrap();
boot.group(acceptGroup, connectGroup)
.channelFactory(NioUdtProvider.MESSAGE_ACCEPTOR)
.option(ChannelOption.SO_BACKLOG, 10)
.option(ChannelOption.SO_REUSEADDR, true)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<UdtChannel>() {
@Override
public void initChannel(final UdtChannel ch) throws Exception {
ch.pipeline().addLast(new MsgEchoServerHandler());
}
});
final ChannelFuture future = boot.bind(1234).sync();
} finally {
acceptGroup.shutdownGracefully().syncUninterruptibly();
connectGroup.shutdownGracefully().syncUninterruptibly();
}
new MsgEchoServer().run();
}
public static void main(final String[] args) throws Exception {
new MsgEchoServer().run();
}
}