2.2.3 零拷贝机制

Netty自己的ByteBuf

ByteBuf是为解决ByteBuffer 的问题和满足网络应用程序开发人员的日常需求而设计的。

JDK ByteBuffer 的缺点

无法动态扩容

长度是固定的,不能动态扩展和收缩,当数据大于ByteBuffer容量时,会发生索引越界异常。

API使用复杂

读写的时候需要手动调用flip()和rewind()等方法,使用时需要非常谨慎的使用这些api,否则很容易出现错误。

ByteBuf做了哪些增强

  1. API操作便携性
  2. 动态扩容
  3. 多种ByteBuf实现
  4. 高效的零拷贝机制

ByteBuf 操作

ByteBuf 三个重要属性capacity容量readerIndex读取位置writerIndex写入位置。

提供了两个指针变量来支持顺序读和写操作,分别是readerIndex和写操作writerIndex。

常用方法定义:

  • 随机访问索引 getByte
  • 顺序读 read*
  • 顺序写 write*
  • 清除已读内容discardReadBytes
  • 清除缓冲区 clear
  • 搜索操作
  • 标记和重置
  • 引用计数和释放

ByteBuf 操作

在这里插入图片描述

bytebuf的常规API操作示例

/**
 * bytebuf的常规API操作示例
 */
public class ByteBufDemo {
    @Test
    public void apiTest() {
        //  +-------------------+------------------+------------------+
        //  | discardable bytes |  readable bytes  |  writable bytes  |
        //  |                   |     (CONTENT)    |                  |
        //  +-------------------+------------------+------------------+
        //  |                   |                  |                  |
        //  0      <=       readerIndex   <=   writerIndex    <=    capacity

        // 1.创建一个非池化的ByteBuf,大小为10个字节
        ByteBuf buf = Unpooled.buffer(10);
        System.out.println("原始ByteBuf为====================>" + buf.toString());
        System.out.println("1.ByteBuf中的内容为===============>" + Arrays.toString(buf.array()) + "\n");

        // 2.写入一段内容
        byte[] bytes = {1, 2, 3, 4, 5};
        buf.writeBytes(bytes);
        System.out.println("写入的bytes为====================>" + Arrays.toString(bytes));
        System.out.println("写入一段内容后ByteBuf为===========>" + buf.toString());
        System.out.println("2.ByteBuf中的内容为===============>" + Arrays.toString(buf.array()) + "\n");

        // 3.读取一段内容
        byte b1 = buf.readByte();
        byte b2 = buf.readByte();
        System.out.println("读取的bytes为====================>" + Arrays.toString(new byte[]{b1, b2}));
        System.out.println("读取一段内容后ByteBuf为===========>" + buf.toString());
        System.out.println("3.ByteBuf中的内容为===============>" + Arrays.toString(buf.array()) + "\n");

        // 4.将读取的内容丢弃
        buf.discardReadBytes();
        System.out.println("将读取的内容丢弃后ByteBuf为========>" + buf.toString());
        System.out.println("4.ByteBuf中的内容为===============>" + Arrays.toString(buf.array()) + "\n");

        // 5.清空读写指针
        buf.clear();
        System.out.println("将读写指针清空后ByteBuf为==========>" + buf.toString());
        System.out.println("5.ByteBuf中的内容为===============>" + Arrays.toString(buf.array()) + "\n");

        // 6.再次写入一段内容,比第一段内容少
        byte[] bytes2 = {1, 2, 3};
        buf.writeBytes(bytes2);
        System.out.println("写入的bytes为====================>" + Arrays.toString(bytes2));
        System.out.println("写入一段内容后ByteBuf为===========>" + buf.toString());
        System.out.println("6.ByteBuf中的内容为===============>" + Arrays.toString(buf.array()) + "\n");

        // 7.将ByteBuf清零
        buf.setZero(0, buf.capacity());
        System.out.println("将内容清零后ByteBuf为==============>" + buf.toString());
        System.out.println("7.ByteBuf中的内容为================>" + Arrays.toString(buf.array()) + "\n");

        // 8.再次写入一段超过容量的内容
        byte[] bytes3 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
        buf.writeBytes(bytes3);
        System.out.println("写入的bytes为====================>" + Arrays.toString(bytes3));
        System.out.println("写入一段内容后ByteBuf为===========>" + buf.toString());
        System.out.println("8.ByteBuf中的内容为===============>" + Arrays.toString(buf.array()) + "\n");
        //  随机访问索引 getByte
        //  顺序读 read*
        //  顺序写 write*
        //  清除已读内容 discardReadBytes
        //  清除缓冲区 clear
        //  搜索操作
        //  标记和重置
        //  完整代码示例:参考
        // 搜索操作 读取指定位置 buf.getByte(1);
        //
    }

}

ByteBuf 动态扩容在这里插入图片描述

选择合适的ByteBuf实现

在这里插入图片描述

Unsafe 的实现

在这里插入图片描述

PooledByteBuf对象、内存复用

在这里插入图片描述

零拷贝机制

在这里插入图片描述

发布了26 篇原创文章 · 获赞 15 · 访问量 3934

猜你喜欢

转载自blog.csdn.net/weixin_43871142/article/details/104598743