一起学Netty(三)之 SimpleChannelInboundHandler

来源:互联网 发布:迷人的保姆 知乎 编辑:程序博客网 时间:2024/05/21 22:29

   其实Netty的知识点还是很零碎的,比如这个SimpleChannelInboundHandler这个类,在《Netty in Action》该书中的原版的Hello world的demo的客户端就是使用的SimpleChannelInboundHandler来作为处理器的,我本来也是使用这个类作为我处理类的,但是做一个新手,这个类还是让我走了一点弯路,我们可以看到SimpleChannelInboundHandler中有一个channelRead0的方法需要我们实现:

尼玛,我记得当时就是使用的channelRead0这个方法,结果服务器端就是不打印,服务器返回的结果,当时客户端是这样写的

[java] view plain copy
  1. package com.lyncc.netty.component.simplehandler;  
  2.   
  3. import io.netty.buffer.ByteBuf;  
  4. import io.netty.channel.ChannelHandlerContext;  
  5. import io.netty.channel.SimpleChannelInboundHandler;  
  6.   
  7. public class BaseClientHandler extends SimpleChannelInboundHandler<ByteBuf>{  
  8.       
  9.     @Override  
  10.     protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {  
  11.         System.out.println("Client channelRead0 received:" + msg);  
  12.     }  
  13.       
  14. //    @Override  
  15. //    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {  
  16. //        System.out.println("Client channelRead received:" + msg);  
  17. //          
  18. //    }  
  19.     
  20.      @Override  
  21.      public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {  
  22.          cause.printStackTrace();  
  23.          ctx.close();  
  24.      }  
  25.   
  26.      
  27.   
  28. }  
结果channelRead0方法就是不运行执行,让我郁闷了有一会,后来,我打开了SimpleChannelInboundHandler的源码,其实这是我很不想看见的,尼玛,一个hello world就已经开始看源代码了,还让不让人活了啊,结果源码中显示SimpleChannelInboundHandler是继承于ChannelInboundHandlerAdapter,重写了channelRead方法:

[java] view plain copy
  1. @Override  
  2.     public void 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来接收,能处理才有鬼,修改一下我们的代码就可以了,重新指定一下处理的类型

[java] view plain copy
  1. package com.lyncc.netty.component.simplehandler;  
  2.   
  3. import io.netty.channel.ChannelHandlerContext;  
  4. import io.netty.channel.SimpleChannelInboundHandler;  
  5.   
  6. public class BaseClientHandler extends SimpleChannelInboundHandler<String>{  
  7.       
  8.     @Override  
  9.     protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {  
  10.         System.out.println("Client channelRead0 received:" + msg);  
  11.     }  
  12.       
  13. //    @Override  
  14. //    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {  
  15. //        System.out.println("Client channelRead received:" + msg);  
  16. //          
  17. //    }  
  18.     
  19.      @Override  
  20.      public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {  
  21.          cause.printStackTrace();  
  22.          ctx.close();  
  23.      }  
  24.      
  25.   
  26. }  
这样就能使channelRead0方法运行了,也怪我眼瞎,书中写的很清楚:



SimpleChannelInboundHandler的channelRead0还有一个好处就是你不用关心释放资源,因为源码中已经帮你释放了,所以如果你保存获取的信息的引用,是无效的~

原创粉丝点击