netty ChannelInboundByteHandlerAdapter

这篇文章分析另外一个表重要比较基础的handler : ChannelInboundByteHandlerAdapter

当我们编写的服务器程序需要直接处理byte的时候,可以直接扩展它来实现inboundhandler,用于处理传送过来的byte数据。。。例如举一个典型的用法:

[java]  view plain copy
  1. public class MyChannelHandler extends ChannelInboundByteHandlerAdapter {  
  2.     @Override  
  3.     protected void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in)  
  4.             throws Exception {  
  5.         // TODO Auto-generated method stub  
  6.         //while (in.isReadable()) {  
  7.             //System.out.print((char)in.readByte());  
  8.         //}  
  9.         final String name = ctx.name();  
  10.         ByteBuf b = ctx.alloc().buffer();   //创建一个buffer用于存放数据  
  11.         b.writeBytes("aaa".getBytes());  
  12.         ctx.pipeline().write(b);   //调用pipeline的write方法,将数据发送出去  
  13.         ctx.pipeline().flush().addListener(new ChannelFutureListener(){  
  14.   
  15.             @Override  
  16.             public void operationComplete(ChannelFuture future)  
  17.                     throws Exception {  
  18.                 // TODO Auto-generated method stub  
  19.                 System.out.println(name);  
  20.                 future.channel().close().sync();  
  21.             }  
  22.         });   
  23.     }  
  24. }  

该类直接继承自ChannelInboundByteHandlerAdapter,然后实现了inboundBufferUpdated方法用于处理读取进来的数据。。。将这个类的对象加入到channel的pipeline上面之后,当这个channel已经有数据读进来之后会调用inboundBufferUpdated方法来处理。。。

我们首先还是来看一下ChannelInboundByteHandlerAdapter的继承体系:


ChannelInboundByteHandlerAdapter直接继承了ChannelStateHandlerAdapter,这个类型在上面的一篇文章中也有说明,它继承了stathandler接口,然后实现了里面的方法,不过这些方法实现的都很简单,无非是从当前pipeline上面向下寻找到另一个stathandler,调用相应的方法。。。

然后ChannelInboundByteHandlerAdapter还实现了ChannelInboundByteHandler接口,这个接口中多定义了一个方法,那就是discardInboundReadBytes。。。

好了,接下来我们来看看ChannelInboundByteHandlerAdapter的定义吧:

[java]  view plain copy
  1. public abstract class ChannelInboundByteHandlerAdapter  
  2.         extends ChannelStateHandlerAdapter implements ChannelInboundByteHandler {  
  3.   
  4.     /** 
  5.      * Create a new unpooled {@link ByteBuf} by default. Sub-classes may override this to offer a more 
  6.      * optimized implementation. 
  7.      */  
  8.     @Override  
  9.     //用于构创建新的buffer  
  10.     public ByteBuf newInboundBuffer(ChannelHandlerContext ctx) throws Exception {  
  11.         return ChannelHandlerUtil.allocate(ctx);  
  12.     }  
  13.   
  14.     @Override  
  15.     //抛弃已经读取的数据  
  16.     public void discardInboundReadBytes(ChannelHandlerContext ctx) throws Exception {  
  17.         ctx.inboundByteBuffer().discardSomeReadBytes();  
  18.     }  
  19.   
  20.     @Override  
  21.     //当有新的收读取到时候,会调用过这个方法来处理这些读取到的数据  
  22.     public final void inboundBufferUpdated(ChannelHandlerContext ctx) throws Exception {  
  23.         inboundBufferUpdated(ctx, ctx.inboundByteBuffer());  
  24.     }  
  25.   
  26.     /** 
  27.      * Callback which will get notifed once the given {@link ByteBuf} received more data to read. What will be done 
  28.      * with the data at this point is up to the implementation. 
  29.      * Implementations may choose to read it or just let it in the buffer to read it later. 
  30.      */  
  31.     //用户自己实现这个方法,真正的用于处理读取到的数据  
  32.     protected abstract void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in) throws Exception;  
  33. }  
public class DiscardClientHandler extends ChannelInboundByteHandlerAdapter {


    private static final Logger logger = Logger.getLogger(
            DiscardClientHandler.class.getName());


    private final int messageSize;
    private ByteBuf content;
    private ChannelHandlerContext ctx;


    public DiscardClientHandler(int messageSize) {
        if (messageSize <= 0) {
            throw new IllegalArgumentException(
                    "messageSize: " + messageSize);
        }
        this.messageSize = messageSize;
    }


    @Override
    public void channelActive(ChannelHandlerContext ctx)
            throws Exception {
        this.ctx = ctx;


        // Initialize the message.
        content = ctx.alloc().directBuffer(messageSize).writeZero(messageSize);


        // Send the initial messages.
        generateTraffic();
    }


    @Override
    public void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in)
            throws Exception {
        // Server is supposed to send nothing, but if it sends something, discard it.
        in.clear();
    }


    @Override
    public void exceptionCaught(ChannelHandlerContext ctx,
            Throwable cause) throws Exception {
        // Close the connection when an exception is raised.
        logger.log(
                Level.WARNING,
                "Unexpected exception from downstream.",
                cause);
        ctx.close();
    }


    long counter;


    private void generateTraffic() {
        // Fill the outbound buffer up to 64KiB
        ByteBuf out = ctx.nextOutboundByteBuffer();
        while (out.readableBytes() < 65536) {
            out.writeBytes(content, 0, content.readableBytes());
        }


        // Flush the outbound buffer to the socket.
        // Once flushed, generate the same amount of traffic again.
        ctx.flush().addListener(trafficGenerator);
    }


    private final ChannelFutureListener trafficGenerator = new ChannelFutureListener() {
        @Override
        public void operationComplete(ChannelFuture future) throws Exception {
            if (future.isSuccess()) {
                generateTraffic();
            }
        }
    };
}


实现代码还是很简单,首先重载了newInboundBuffer方法,至于inboundBufferUpdated方法,其实是用来调用用户自定义的inboundBufferUpdated方法来来处理新进来的数据。。

因此用户编码的时候,只需要继承ChannelInboundByteHandlerAdapter类,然后实现inboundBufferUpdated方法就可以了。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值