以编程方式关闭netty

我正在使用netty 4.0.24.Final。

我需要以编程方式启动/停止netty服务器。
启动服务器时,线程被阻止

f.channel().closeFuture().sync()

请帮助提供一些提示如何正确执行此操作。 下面是Main类调用的EchoServer。 谢谢。

 package nettytests; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; public class EchoServer { private final int PORT = 8007; private EventLoopGroup bossGroup; private EventLoopGroup workerGroup; public void start() throws Exception { // Configure the server. bossGroup = new NioEventLoopGroup(1); workerGroup = new NioEventLoopGroup(1); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 100) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoServerHandler()); } }); // Start the server. ChannelFuture f = b.bind(PORT).sync(); // Wait until the server socket is closed. Thread gets blocked. f.channel().closeFuture().sync(); } finally { // Shut down all event loops to terminate all threads. bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public void stop(){ bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } package nettytests; public class Main { public static void main(String[] args) throws Exception { EchoServer server = new EchoServer(); // start server server.start(); // not called, because the thread is blocked above server.stop(); } } 

更新:我以下列方式更改了EchoServer类。 我们的想法是在新线程中启动服务器并保留指向EventLoopGroups的链接。 这是正确的方法吗?

 package nettytests; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; /** * Echoes back any received data from a client. */ public class EchoServer { private final int PORT = 8007; private EventLoopGroup bossGroup; private EventLoopGroup workerGroup; public void start() throws Exception { new Thread(() -> { // Configure the server. bossGroup = new NioEventLoopGroup(1); workerGroup = new NioEventLoopGroup(1); Thread.currentThread().setName("ServerThread"); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 100) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoServerHandler()); } }); // Start the server. ChannelFuture f = b.bind(PORT).sync(); // Wait until the server socket is closed. f.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { // Shut down all event loops to terminate all threads. bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } }).start(); } public void stop() throws InterruptedException { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } 

一种方法是做一些像:

 // once having an event in your handler (EchoServerHandler) // Close the current channel ctx.channel().close(); // Then close the parent channel (the one attached to the bind) ctx.channel().parent().close(); 

这样做将最终得到以下结果:

 // Wait until the server socket is closed. Thread gets blocked. f.channel().closeFuture().sync(); 

主要部分无需额外的线程。 现在的问题是:什么样的事件? 这取决于你……可能是echo处理程序中的一条消息“shutdown”,它将被视为关闭的顺序,而不仅仅是“退出”,它将变为仅关闭客户端通道。 可能是别的……

如果你没有从子通道(通过你的处理程序)处理关闭,而是通过另一个进程(例如查找存在的停止文件),那么你需要一个额外的线程来等待这个事件,然后直接建立一个channel.close()其中channel将是父节点(例如来自f.channel() )…

存在许多其他解决方案