2016-03-18 19 views
1

我對netty很新,我想創建一個TCP服務器,它在實例化連接時執行自定義應用層握手。握手後,我想將消息(ByteBuf)傳遞給一個隊列,以便它們可以被其他線程處理。Netty pipleline中的多ChannelInboundHandlerAdapter

我的問題是,我可以在通道管道中有多個ChannelInboundHandlerAdapter嗎?一個用於應用層握手協議,另一個用於將消息傳遞給隊列。此外,我想知道消息如何流經管道。如果一個處理程序(或解碼器/編碼器)接收到消息,它是如何傳遞給另一個處理程序的。

具體而言,如果我從here更改EchoServer並添加另一個ChannelInboundHandlerAdapter,echo服務器處理程序將停止接收任何消息。

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

ChannelInboundHandlerAdapterChannelInBoundHandler接口的適配器類。開始時,您可以使用SimpleChannelInboundHandler(或者更復雜的是,您可以擴展適配器類,編寫自己的處理程序,擴展ChannelInboundHandlerAdapter)。 在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)會拋出異常{ByteHandlerContext ctx,Object msg} Byt eBuf in = null; \t \t嘗試{ \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 new EchoServerHandler(channels));' EchoServerHandler仍然沒有調用 – Hossein

+1

儘量不要調用'finally {in.release()}'看看這個線程http://stackoverflow.com/questions/23419433/netty-hello-world-example-not-working –

0

我要提醒的是:

只有一個SimpleChannelInboundHandler extention可以加入到管線鏈。 因爲SimpleChannelInboundHandler有一個finally代碼塊會釋放所有的味精。

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

}