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

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

 

netty 提供的解码

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

  MessageToMessageEncoder 根据 消息对象 编码为消息对象

对于 netty的数据传递都是ByteBuf,我们一般重写以上的解码器、编码器来实现自己的逻辑

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的读取
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数据为空或满的情形,作为数据容器,要存在边界值检查,确保读写安全。

 
时间: 2024-10-10 10:02:52

Netty——高级内置解码器、编码器、ByteBuf的相关文章

Netty 核心容器之ByteBuf 结构详解

原文链接 Netty 核心容器之ByteBuf 结构详解 Java的NIO模块提供了ByteBuffer作为其字节存储容器,但是这个类的使用过于复杂,因此Netty实现了ByteBuf来替换NIO的ByteBuffer类,ByteBuf具有以下的特点: 自定义用户缓冲区域的类型 实现字节区域的深浅拷贝 容量可按需增长 在读写模式直接不需要像JDK的ByteBuffer那样调用flip()方法切换 读写使用不同的索引,即readIndex和writeIndex 支持方法链式调用 支持引用计数和池化

netty高级篇(3)-HTTP协议开发

一.HTTP协议简介 应用层协议http,发展至今已经是http2.0了,拥有以下特点: (1) CS模式的协议 (2) 简单 - 只需要服务URL,携带必要的请求参数或者消息体 (3) 灵活 - 任意类型,传输内容类型由HTTP消息头中的Content-Type加以标记 (4) 无状态 - 必须借助额外手段,比如session或者cookie来保持状态 1.1 HTTP请求消息(HttpRequest) 客户端发送一个HTTP请求到服务器的请求消息包括以下格式:请求行(request line

Netty高级

Netty快速入门 什么是Netty Netty 是一个基于 JAVA NIO 类库的异步通信框架,它的架构特点是:异步非阻塞.基于事件驱动.高性能.高可靠性和高可定制性. Netty应用场景 1.分布式开源框架中dubbo.Zookeeper,RocketMQ底层rpc通讯使用就是netty. 2.游戏开发中,底层使用netty通讯. 为什么选择netty 在本小节,我们总结下为什么不建议开发者直接使用JDK的NIO类库进行开发的原因: 1)      NIO的类库和API繁杂,使用麻烦,你需

Netty(7)源码-ByteBuf

一.ByteBuf工作原理 1. ByteBuf是ByteBuffer的升级版: jdk中常用的是ByteBuffer,从功能角度上,ByteBuffer可以完全满足需要,但是有以下缺点: ByteBuffer一旦分配完成,长度固定,不能动态扩展和收缩,当需要编码的POJO对象大于分配容量时发生索引越界异常 ByteBuffer只要一个标识位置的指针postion,读写切换比较麻烦,flip rewind等操作 功能有限 ByteBuf依然是Byte数组缓冲区,拥有ByteBuffer的一切功能

Netty——高级发送和接收数据handler处理器

netty发送和接收数据handler处理器 主要是继承 SimpleChannelInboundHandler 和 ChannelInboundHandlerAdapter 一般用netty来发送和接收数据都会继承SimpleChannelInboundHandler和ChannelInboundHandlerAdapter这两个抽象类,那么这两个到底有什么区别呢? 其实用这两个抽象类是有讲究的,在客户端的业务Handler继承的是SimpleChannelInboundHandler,而在服

netty pooled vs unpooled ByteBuf

Whats the difference between Pooled vs Unpooled and Direct vs Heap in ByteBuf? Like , what does pooled means in context of a message received , because object like HttpRequest is created from ByteBuf in one of HttpRequestDecoder and then released in

一起学Netty(五)之 初识ByteBuf和ByteBuf的常用API

网络传输的载体是byte,这是任何框架谁也逃脱不了的一种规定,JAVA的NIO提供了ByteBuffer,用来完成这项任务,当然ByteBuffer也很好的完成了这个任务,Netty也提供了一个名字很相似的载体叫做ByteBuf,相比于ByteBuf而言,它有着更加更多友善的API,也更加易于维护,并且它可以扩容 一般来说,ByteBuf都是维护一个byte数组的,它的内部格式是长成这个样子的 * +-------------------+------------------+---------

Netty权威指南

Netty权威指南(异步非阻塞通信领域的经典之作,国内首本深入剖析Netty的著作,全面系统讲解原理.实战和源码,带你完美进阶Netty工程师.) 李林锋 著   ISBN 978-7-121-23343-2 2014年6月出版 定价:79.00元 524页 16开 编辑推荐 - 资深一线专家诚意之作,总结多年实践经验,带你全面掌握Java高并发异步通信的首选框架——Netty. - Facebook.阿里巴巴.1号店.并发编程网.JBoss等多位资深技术专家联名力荐. <Netty权威指南>

【Netty】ChannelHandler和codec

一.前言 前面学习了Netty的codec框架,下面接着学习ChannelHandler与codec之间的关联. 二.ChannelHandler和codec Netty为不同的协议提供了处理器和编解码器,可以开箱即用,这些工具支持SSL / TLS和WebSocket,以及通过数据压缩使得HTTP有更好的性能. 2.1 使用SSL/TLS保护Netty应用程序 由于数据隐私非常重要,而SSL和TLS等加密协议用于处理数据隐私,这些协议在其他协议之上以实现数据安全性.安全网站会使用这种协议,同时