2015-01-19 11 views
12

Ich bin mit netty 4.0.24.Final.Shutdown netty programmatisch

Ich brauche zu starten/netty Server programmatisch zu stoppen.
auf den Server gestartet hat, wird der Faden bei

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

mit einigen Hinweisen helfen Bitte blockiert, wie es richtig zu tun. Unten ist der Echoserver, die von der Hauptklasse aufgerufen wird. Danke.

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

UPDATE: ich die Echoserver-Klasse in der folgenden Art und Weise verändert. Die Idee ist, den Server in einem neuen Thread zu starten und die Links zu den EventLoopGroups zu bewahren. Ist das der richtige Weg?

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

Antwort

9

Eine Möglichkeit ist, wie etwas zu machen: für ein extra Thread

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

Keine Notwendigkeit, auf Hauptteil:

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

Auf diese Art und Weise die folgenden wird am Ende. Nun ist die Frage: Welche Art von Veranstaltung? Es liegt an Ihnen ... Könnte eine Meldung in der Echo-Handler als „Shutdown“, die als Auftrag der Abschaltung genommen werden und nicht nur „beenden“, die das Schließen nur den Client-Kanal verwandelt. Könnte etwas anderes sein ...

Wenn Sie nicht das Herunterfahren von einem Kind-Kanal (also durch Ihre Handler), sondern durch einen anderen Prozess (zum Beispiel Suche nach einer Stop-Datei) behandeln, dann benötigen Sie einen zusätzlichen Thread wird auf dieses Ereignis warten und dann direkt eine channel.close() machen, wobei der Kanal der übergeordnete Kanal sein wird (von f.channel()) zum Beispiel ...

Viele andere Lösungen existieren.