Выключение netty программно

Я использую netty 4.0.24.Окончательный.

мне нужно программно запустить / остановить сервер netty.
При запуске сервера поток блокируется в

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

пожалуйста, помогите с некоторыми подсказками, как это сделать правильно. Ниже приведен 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<SocketChannel>() {
                 @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<SocketChannel>() {
                            @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();
    }
}

1 ответов


один из способов-сделать что-то вроде:

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

отсутствие потребности для дополнительного потока на основной части. Теперь возникает вопрос: какого рода событие? Это до вас... Может быть сообщение в обработчике Эха как "shutdown", которое будет принято как порядок выключения, а не только" quit", который превратится в закрытие только клиентского канала. Может, что-то другое...

если вы не обрабатываете завершение работы от a дочерний канал (так через ваш обработчик), но через другой процесс (например, ищет существующий файл остановки), тогда вам нужен дополнительный поток, который будет ждать этого события, а затем непосредственно сделает channel.close() где канал будет родительским (от f.channel()) например...

существует множество других решений.