netty:protobuf的编码器ProtobufVarint32LengthFieldPrepender()、解码器ProtobufVarint32FrameDecoder()

来源:互联网 发布:最搞笑的网络歪歌 编辑:程序博客网 时间:2024/06/01 07:50

首先,下图是常规的netty内置的protibuf编解码器的使用


本文主要介绍下面2个编解码器:

1. ProtobufVarint32LengthFieldPrepender()
对protobuf协议的的消息头上加上一个长度为32的整形字段,用于标志这个消息的长度。
这里是官方举的例子,实际这个字段的长度是5byte



(1)computeRawVarint32Size(final int value)
计算value的大小,二进制每7位为一个单位。


(2)writeRawVarint32(bodyLen)
value值是长度,0x7f的十进制值是127 (00000000 00000000 00000000 01111111),127取反得二进制(11111111 11111111 11111111 10000000)把value和127取反的二进制进行&运算
1)只要value不大于127,则把长度写为直接写入,并直接返回。
2)如果大于127,则把value与127进行&运算,只取value二进制的低7位为1的值(其它位置0),接着把value与0x80(10000000)进行|运算,把value第8位的值变为1后写入(如果以byte类型读,则恒为负数),只取128-255的值。再把value无符号右移7位,继续下一次循环


2. ProtobufVarint32FrameDecoder()
这是针对protobuf协议的ProtobufVarint32LengthFieldPrepender()所加的长度属性的解码器
官方例子:


protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {    in.markReaderIndex();    // 因为length的长度为5个字节,所以申请一个5个字节的数组    final byte[] buf = new byte[5];    for (int i = 0; i < buf.length; i ++) {        //判断是否可读,不可读要重置read的索引        if (!in.isReadable()) {            in.resetReaderIndex();            return;        }        //从in里面读取数据放入数组,此时buf[i]的值有两种情况,        //(1)正数,代表当前数组i的值已经是长度二进制的最高位的值(以8个字节为单位的byte),可以进行读取。        //(2)负数,代表当前值大于127,所以在编码时与0x80(10000000)做过|运算,所以不能读取,继续进行for循环        buf[i] = in.readByte();        if (buf[i] >= 0) {            int length = CodedInputStream.newInstance(buf, 0, i + 1).readRawVarint32();            if (length < 0) {                throw new CorruptedFrameException("negative length: " + length);            }            if (in.readableBytes() < length) {                in.resetReaderIndex();                return;            } else {                out.add(in.readBytes(length));                return;            }        }    }    // Couldn't find the byte whose MSB is off.    throw new CorruptedFrameException("length wider than 32-bit");}


4 0
原创粉丝点击