1. 程式人生 > >一起學Netty(三)之 SimpleChannelInboundHandler

一起學Netty(三)之 SimpleChannelInboundHandler

 其實Netty的知識點還是很零碎的,比如這個SimpleChannelInboundHandler這個類,在《Netty in Action》該書中的原版的Hello world的demo的客戶端就是使用的SimpleChannelInboundHandler來作為處理器的,我本來也是使用這個類作為我處理類的,但是做一個新手,這個類還是讓我走了一點彎路,我們可以看到SimpleChannelInboundHandler中有一個channelRead0的方法需要我們實現:

尼瑪,我記得當時就是使用的channelRead0這個方法,結果伺服器端就是不列印,伺服器返回的結果,當時客戶端是這樣寫的

  1. package com.lyncc.netty.component.simplehandler;  
  2. import io.netty.buffer.ByteBuf;  
  3. import io.netty.channel.ChannelHandlerContext;  
  4. import io.netty.channel.SimpleChannelInboundHandler;  
  5. publicclass BaseClientHandler extends SimpleChannelInboundHandler<ByteBuf>{  
  6.     @Override
  7.     protected
    void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {  
  8.         System.out.println("Client channelRead0 received:" + msg);  
  9.     }  
  10. //    @Override
  11. //    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  12. //        System.out.println("Client channelRead received:" + msg);
  13. //        
  14. //    }
  15.      @Override
  16.      publicvoid exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {  
  17.          cause.printStackTrace();  
  18.          ctx.close();  
  19.      }  
  20. }  
結果channelRead0方法就是不執行執行,讓我鬱悶了有一會,後來,我打開了SimpleChannelInboundHandler的原始碼,其實這是我很不想看見的,尼瑪,一個hello world就已經開始看原始碼了,還讓不讓人活了啊,結果原始碼中顯示SimpleChannelInboundHandler是繼承於ChannelInboundHandlerAdapter,重寫了channelRead方法:
  1. @Override
  2.     publicvoid channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {  
  3.         boolean release = true;  
  4.         try {  
  5.             if (acceptInboundMessage(msg)) {  
  6.                 @SuppressWarnings("unchecked")  
  7.                 I imsg = (I) msg;  
  8.                 channelRead0(ctx, imsg);  
  9.             } else {  
  10.                 release = false;  
  11.                 ctx.fireChannelRead(msg);  
  12.             }  
  13.         } finally {  
  14.             if (autoRelease && release) {  
  15.                 ReferenceCountUtil.release(msg);  
  16.             }  
  17.         }  
  18.     }  
原來我們SimpleChannelInboundHandler後面指定了處理型別,也就是原始碼中的"I",acceptInboundMessage方法判斷msg是不是SimpleChannelInboundHandler中指定的型別,我們這邊指定的是ByteBuf,感覺沒啥問題啊,但是我們忽略了一個問題,我們客戶端中有3個處理器,兩個inbound型別的處理器,其中一個就是HelloWorldClientHandler,還有一個就是StringDecoder,此時我內心是崩潰的,尼瑪,上一個處理器已經把伺服器端的資訊轉化成String,我還用ByteBuf來接收,能處理才有鬼,修改一下我們的程式碼就可以了,重新指定一下處理的型別
  1. package com.lyncc.netty.component.simplehandler;  
  2. import io.netty.channel.ChannelHandlerContext;  
  3. import io.netty.channel.SimpleChannelInboundHandler;  
  4. publicclass BaseClientHandler extends SimpleChannelInboundHandler<String>{  
  5.     @Override
  6.     protectedvoid channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {  
  7.         System.out.println("Client channelRead0 received:" + msg);  
  8.     }  
  9. //    @Override
  10. //    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  11. //        System.out.println("Client channelRead received:" + msg);
  12. //        
  13. //    }
  14.      @Override
  15.      publicvoid exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {  
  16.          cause.printStackTrace();  
  17.          ctx.close();  
  18.      }  
  19. }  
這樣就能使channelRead0方法運行了,也怪我眼瞎,書中寫的很清楚:


SimpleChannelInboundHandler的channelRead0還有一個好處就是你不用關心釋放資源,因為原始碼中已經幫你釋放了,所以如果你儲存獲取的資訊的引用,是無效的~

這個是學習Netty走的一段彎路,在這裡跟大家share一下~