如何在Netty 4中正确关闭UDT服务器

时间:2013-08-01 11:18:12

标签: netty

我正在尝试用shutDownGracefully()关闭我的UDT服务器(Netty 4.0.5.Final)并在同一端口重新打开它。不幸的是,我总是得到下面的套接字例外,虽然它等到未来完成。我还添加了套接字选项SO_REUSEADDR

这样做的正确方法是什么?

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)

一个小测试程序演示了这个问题:

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

}

2 个答案:

答案 0 :(得分:0)

组表示线程。 shutdowngracefully()是释放线程资源,而不是关闭套接字。因此,您需要显式关闭套接字,以便再次重新使用该端口,如下所示。

future.Channel().close()

这意味着您需要在代码中存储创建的服务器通道以实现近距离目的。

答案 1 :(得分:0)

这是a known issue。解决方法是在再次绑定之前等待大约5秒钟。