阅读 128

Netty——高级内置解码器、编码器、ByteBuf

Netty——高级内置解码器、编码器、ByteBuf

netty通讯需要对数据进行编码,解码,于是我们需要用到netty的编码器、解码器

 

netty 提供的解码

  DelimiterBasedFrameDecoder 解决TCP的粘包解码器
  StringDecoder              消息转成String解码器
  LineBasedFrameDecoder      自动完成标识符分隔解码器
  FixedLengthFrameDecoder    固定长度解码器,二进制
  Base64Decoder base64       器
netty 提供的编码器
   Base64Encoder  base64编码器
  StringEncoder  消息转成String编码器
  LineBasedFrameDecoder  自动完成标识符分隔器

  MessageToMessageEncoder 根据 消息对象 编码为消息对象
1、DelimiterBasedFrameDecoder 解决TCP的粘包解码器
IODecoder  继承

复制代码

复制代码

/**
 * 解码
 * DelimiterBasedFrameDecoder  防止 沾包
 * @author flm 
 * 2017年10月30日
 */
public class IODecoder extends DelimiterBasedFrameDecoder {

    public static final AttributeKey<DeviceSession> KEY = AttributeKey.valueOf("IO"); // 保存
    private static final Logger log = Logger.getLogger(IODecoder.class);

    // 防止 沾包 分隔符
    private static ByteBuf delimiter = Unpooled.copiedBuffer("\n".getBytes());  // 沾包 分割符 \n
    private static int maxFrameLength = 1024 * 6;                   //数据大小

    
    
    public IODecoder() {
        super(maxFrameLength, delimiter);
    }

    /**
     * 重新 自定义解码
     */
    @Override
    protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
        // 对数据  buffer 解码
        return super.decode(ctx, buffer);
    }
}

复制代码

复制代码

 

2、MessageToMessageEncoder   编码器

复制代码

复制代码

/**
 * 指令 编码 
 * MessageToMessageEncoder<PushEntity>
 * 把 PushEnty 编码为string
 * @author flm
 * 2017年11月3日
 */
public class IOEncoder extends MessageToMessageEncoder<PushEntity> {

    private static final Logger LOG = Logger.getLogger(IOEncoder.class);

    
    public IOEncoder() {
        super();
    }
    
    
    /**
     * 重写 编码
     */
    @Override
    protected void encode(ChannelHandlerContext ctx, PushEntity msg, List<Object> out) throws Exception {
        try {
        PushEntity push = (PushEntity) msg;

            }
    
            // 以字符串 形式 发送
            out.add(ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(msg.toString()), Charset.defaultCharset()));
            
            
        } catch (Exception e) {
            
            e.printStackTrace();
            
        }
    }
}

复制代码

复制代码

 

3、 FixedLengthFrameDecoder 固定长度解码器,二进制

复制代码

复制代码

/** 
 *  
 * 功能描述:协议消息解码器  
 * 把 btyeBuf 转为 RootMessage对象
 *     
 */
public class GT06MsgDecoder extends LengthFieldBasedFrameDecoder
{
    public GT06MsgDecoder()
    {
        super(65540, 2, 1, 2, 0);   //继承
    }

  /*
  * 重写 解码
  */
    @Override
    public Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception
    {
        ByteBuf frame = (ByteBuf) super.decode(ctx, in);        
     // 读取 ByteBuf 是根据 位数来读取的
        try
        {
            if (frame == null)
            {
                return null;
            }
            
            int frameLen = frame.readableBytes();
            
            // 起始位
            byte[] header = new byte[GT06Constant.START_DELIMITER_LEN];
            
            frame.readBytes(header);
            
            // 是否是0x79 0x79 开头的扩展包
            boolean extPacket = false;
            
            if(Arrays.equals(GT06Constant.PACKET_START_EXT, header))
            {
                extPacket = true;
            }
            
            int contentLen = MessageUtils.getContentLen(frameLen, extPacket);
            
            // 跳过包长度
            frame.skipBytes(MessageUtils.getPacketSizeLen(extPacket));
            
            // 消息内容
            byte[] msgContent = new byte[contentLen];
            
            // 消息序列号
            byte[] sequence = new byte[GT06Constant.MESSAGE_SERIAL_LEN];
            
            // crc校验码
            byte[] crc = new byte[GT06Constant.CRC_ITU_LEN];
            
            // 终止符
            byte[] endDelimiter = new byte[GT06Constant.END_DELIMITER_LEN];

         return new RootMessage(action, sequence, msgContent);
        }
        finally
        {
            if(frame != null)
            {
                frame.release();
            }
        }
    }

复制代码

复制代码

 

其它的编码器,解码器都大同小异,不懂的可以看源码




其实解码、编码,最最重要的是对BtyeBuf的读取

 

读操作主要提供以下功能:
  • readByte:取1字节的内容;

  • skipBytes: 跳过内容

  • readUnsignedByte:取1字节的内容,返回((short) (readByte() & 0xFF));(能把负数转换为无符号吗?)

  • readShort:取2字节的内容,返回转换后的short类型;

  • readUnsignedShort:取2字节的内容,返回readShort() & 0xFFFF

  • readMedium:取3字节的内容,返回转换后的int类型;

  • readUnsignedMedium:取3字节的内容,返回转换后的int类型;

  • readInt:取4字节的内容;

  • readUnsignedInt:取4字节的内容,返回readInt() & 0xFFFFFFFFL

  • readLong:取8字节的内容;

  • readChar:取1字节的内容;

  • readFloat:取4字节的int内容,转换为float类型;

  • readDouble:取8字节的long内容,转换为double类型;

  • readBytes:取指定长度的内容,返回ByteBuf类型;

  • readSlice:取指定长度的内容,返回ByteBuf类型;

  • readBytes:取指定长度的内容到目标容器。

 写操作

写操作提供的功能主要是往ByteBuf中写入byte内容,不再一一赘述。主要区别在于写入前根据类型转换为相对应长度的byte数组。

主要函数是:writeBoolean、writeByte、writeShort、writeMedium、writeInt、writeLong、writeChar、writeFloat、writeDouble、writeBytes、writeZero。

边界值安全

不论读或写,肯定会存在ByteBuf数据为空或满的情形,作为数据容器,要存在边界值检查,确保读写安全。


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐