2016-03-18 1 views
1

Я совершенно новый с netty, я хочу создать TCP-сервер, который выполняет установление связи пользовательского приложения, когда соединение должно быть создано. После установления связи я хочу передать сообщения (ByteBuf) в очередь, чтобы они могли обрабатываться некоторыми другими потоками.Multiple ChannelInboundHandlerAdapter в Netty pipleline

Мой вопрос: могу ли я иметь несколько ChannelInboundHandlerAdapter в конвейере канала? один для протокола подтверждения связи прикладного уровня, а другой для передачи сообщения в очередь. Кроме того, я хочу знать, как сообщения проходят по конвейеру. Если сообщение получено у одного обработчика (или декодера/кодировщика), как оно передается другому обработчику.

В частности, если я изменил EchoServer с here и добавлю другой ChannelInboundHandlerAdapter, обработчик эхо-сервера перестанет получать какие-либо сообщения.

ServerBootstrap b = new ServerBootstrap(); 
      b.group(group) 
      .channel(NioServerSocketChannel.class) 
      .localAddress(new InetSocketAddress(port)) 
      .childHandler(new ChannelInitializer<SocketChannel>() { 
       @Override 
       public void initChannel(SocketChannel ch) 
        throws Exception { 
       ch.pipeline().addLast(new ChannelInboundHandlerAdapter() { 
        @Override 
        public void channelRead(ChannelHandlerContext ctx, 
          Object msg) { 
          } 
          }); 

        ch.pipeline().addLast(
         new EchoServerHandler()); 
       } 
       }); 

Моя логика: есть 2 ChannelInboundHandlerAdapter тогдашних делать рукопожатие с первым обработчиком и отбрасывать пакеты, если они не соответствуют критериям рукопожатия, а затем передавать сообщения в очередь через второй ChannelInboundHandlerAdapter. Правильно ли моя логика? Если не так, как это должно быть?

спасибо.

ответ

2

ChannelInboundHandlerAdapter - это класс адаптера для интерфейса ChannelInBoundHandler. Для начала вы можете использовать SimpleChannelInboundHandler (или, что более сложно, вы можете расширить класс адаптера, называя свой собственный обработчик, который расширяет ChannelInboundHandlerAdapter). SimpleCHannelInboundHandler автоматически отправляет сообщение после channelRead() (и тем самым передает его следующему обработчику в ChannelPipeline).

Для использования проще SimpleChannelInboundHandler увидеть эту нить Netty hello world example not working

Так вместо этого ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {}

вы должны написать новый класс, который расширяет SimpleChannelInboundHandler как

public class MyHandler extends SimpleChannelInboundHandler{ 


    @Override 
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { 


     try { 
      System.out.println(in.toString(io.netty.util.CharsetUtil.US_ASCII)); 
     } finally { 
      in.release(); 
     } 


    } 
} 

и ссылаться на него как

public void initChannel(SocketChannel ch) throws Exception { 
         ch.pipeline().addLast(new MyHandler()); 
        } 

Как указано выше, SimpleCHannelInboundHandler автоматически отправляет сообщение после channelRead() (и тем самым передает его следующему обработчику в ChannelPipeline).

Если вы используете ChannelInboundHandlerAdapter вы должны осуществить прохождение сообщения/события к следующему обработчику себя

Обработчик должен вызывать методы распространения событий в ChannelHandlerContext ctx направить событие в свой следующий обработчик. (в классе SimpleChannelInboundHandler это еще реализован)

public class MyInboundHandler extends ChannelInboundHandlerAdapter { 
    @Override 
    public void channelActive(ChannelHandlerContext ctx) { 
     System.out.println("Connected!"); 
     ctx.fireChannelActive(); 
    } 
} 

Смотрите эту http://netty.io/4.0/api/io/netty/channel/ChannelPipeline.html

+0

Я до сих пор есть некоторые проблемы:. 'ch.pipeline() addLast (новый SimpleChannelInboundHandler () { \t \t защищены void channelRead0 (ChannelHandlerContext ctx, Object msg) throws Exception { Byt eBuf in = null; \t \t try { \t \t in = (ByteBuf) (msg); \t \t in.retain(); \t \t} finally { \t \t in.release(); \t \t} \t \t} \t \t}); ch.pipeline(). AddLast ( \t \t новый EchoServerHandler (каналы)); EchoServerHandler по-прежнему не называется – Hossein

+1

попробуйте не вызывать 'finally {in.release()}' посмотреть эту тему http://stackoverflow.com/questions/23419433/netty-hello-world-example-not-working –

0

Я должен напомнить, что:

Только один SimpleChannelInboundHandler продление может быть добавить в цепи трубопровода. Поскольку SimpleChannelInboundHandler имеет, наконец, кодовый блок, освободит все сообщения.

@Override 
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 
    boolean release = true; 
    try { 
     if (acceptInboundMessage(msg)) { 
      @SuppressWarnings("unchecked") 
      I imsg = (I) msg; 
      channelRead0(ctx, imsg); 
     } else { 
      release = false; 
      ctx.fireChannelRead(msg); 
     } 
    } finally { 
     if (autoRelease && release) { 
      //release all handled messages,so the next handler won't be executed 
      ReferenceCountUtil.release(msg);** 
     } 
    } 
} 

Использование ChannelInboundHandlerAdapter вместо:

public class CustomizeChannelInboundHandler extends ChannelInboundHandlerAdapter { 
    @Override 
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 
    System.out.println("do something you like!") 

    super.channelRead(ctx, msg); 
    } 

}

Смежные вопросы