Netty 源码分析之ByteToMessageDecoder

欢迎关注技术公众号

ByteToMessageDecoder是netty中的一个ChannelHandler,用于将ByteBuf转换成Message,message可以是POJO等等,转换后继续在ChannelPipeline中传递,Decoder和Encoder等设置显示了netty的ChannelPipeline带来的强大的灵活性,并且可以使我们复用很多逻辑代驾,分离职责。

ByteToMessageDecoder继承自ChannelHandlerAdapter,需要开发者实现的是decode方法

protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception;

ctx是decode属于的ChannelHandlerContext,in是用来读取的数据,out是我们转换后的对象列表
一个将Byte转换成Integer的例子

class ByteToIntegerDecoder extends ByteToMessageDecoder{
		@Override
		protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
			while(in.readableBytes() > 4){
				out.add(in.readInt());
			}
		}
	}

分析源码中较为关键的channelRead

public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof ByteBuf) {
            RecyclableArrayList out = RecyclableArrayList.newInstance();
            try {
                ByteBuf data = (ByteBuf) msg;
                first = cumulation == null;
                if (first) {
                    cumulation = data;
                } else {
                    cumulation = cumulator.cumulate(ctx.alloc(), cumulation, data);
                }
                callDecode(ctx, cumulation, out);
            } catch (DecoderException e) {
                throw e;
            } catch (Throwable t) {
                throw new DecoderException(t);
            } finally {
                if (cumulation != null && !cumulation.isReadable()) {
                    cumulation.release();
                    cumulation = null;
                }
                int size = out.size();

                for (int i = 0; i < size; i ++) {
                    ctx.fireChannelRead(out.get(i));
                }
                out.recycle();
            }
        } else {
            ctx.fireChannelRead(msg);
        }
    }

cumulation是代表累加的byte数据,即上一次decode剩下的byte,cumulator是累加器,默认使用MERGE_CUMULATOR就是使用内存复制来进行累加。累加完之后调用callDecode(ctx, cumulation, out),callDecode中循环调用我们要实现的抽象方法decode(ctx,in,out)来解码,知道不能继续解。
在finally中对out列表中的每一个对象调用ctx.fireChannelRead(out.get(i))
触发ChannelPipeline后面的ChannelHandler的channelRead事件

欢迎关注技术公众号

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

高级Java进阶之路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值