netty之SimpleChannelInboundHandler

Posted 叶长风

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了netty之SimpleChannelInboundHandler相关的知识,希望对你有一定的参考价值。

netty之SimpleChannelInboundHandler


在最开始学些netty的时候,写的服务端demo的handler,继承的都是ChannelInboundHandlerAdapter,客户端继承的是SimpleChannelInboundHandler,当然最开始学的时候都是在不断的写demo,并不清楚为何两边继承的类还不一样,还想过服务端handler也继承SimpleChannelInboundHandler类,这样就不需要每次将数据转换成我们需要的类型了,但是后来逐渐了解用法后,便放弃了使用SimpleChannelInboundHandler作为服务端处理类。

首先说ChannelInboundHandlerAdapter类,每次使用都需要将msg转换成我们需要的类型,如下:

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception 
        String body = (String) msg;
        System.out.println("The time server receive order : " + body + "; the counter is : " + ++counter);
        String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date(System.currentTimeMillis()).toString() : "BAD ORDER";
        currentTime = currentTime + System.getProperty("line.separator");
        ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());
        ctx.writeAndFlush(resp);
    

如上就是在编写一个最简单的demo程序的时候将msg转化成一个字符串,然后输出字符串,但是只是这样写还是不行的,还要在pipline中添加StringDecoder的转码,如下:

protected void initChannel(SocketChannel socketChannel) throws Exception 
            socketChannel.pipeline().addLast(new LineBasedFrameDecoder(1024));
            socketChannel.pipeline().addLast(new StringDecoder());
            socketChannel.pipeline().addLast(new TimeServerHandler());
        

这样写完后,在运行server程序的时候,channelRead方法就会正确的执行,不加上面吃力handler,程序会channelRead方法处一直阻塞住,不会得到正确的响应。

再看SimpleChannelInboundHandler的源码的时候,class最上面的注释就是:

/**
 * @link ChannelInboundHandlerAdapter which allows to explicit only handle a specific type of messages.
 *
 * For example here is an implementation which only handle @link String messages.
 *
 * <pre>
 *     public class StringHandler extends
 *             @link SimpleChannelInboundHandler&lt;@link String&gt; 
 *
 *         @code @Override
 *         protected void channelRead0(@link ChannelHandlerContext ctx, @link String message)
 *                 throws @link Exception 
 *             System.out.println(message);
 *         
 *     
 * </pre>
 */
public abstract class SimpleChannelInboundHandler<I> extends ChannelInboundHandlerAdapter 

继承ChannelInboundHandlerAdapter,泛型指定处理类型,用法在注释中写的十分清楚,因此客户端handler的写法则是继承SimpleChannelInboundHandler类后,指定处理类型,实现的方法中的参数就是我们所需的类型,十分方便。

另外一个需要知道的就是,SimpleChannelInboundHandler覆盖了channelRead方法后,释放了资源:

 @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) 
                ReferenceCountUtil.release(msg);
            
        
    

在这释放资源后,我们如果想传递到下一个handler中是没有作用的,因此最后在服务端的程序中不要使用这个类,服务端还是使用ChannelInboundHandlerAdapter,客户端继承这个类进行数据处理后无需释放掉资源,因此才知道那么多的博客上写的使用这两个类是有一定讲究的,服务端使用ChannelInboundHandlerAdapter,客户端使用SimpleChannelInboundHandler。

以上是关于netty之SimpleChannelInboundHandler的主要内容,如果未能解决你的问题,请参考以下文章

读后感Netty 系列之 Netty 高性能之道 - 相比 Mina 怎样 ?

Netty系列之Netty高性能之道

Netty系列之Netty高性能之道

Netty 系列之 Netty 高性能之道

Netty7# Netty之事件传递

实战Netty系列之Netty高性能之道