Netty 学习笔记(2) ------ 数据传输载体ByteBuf

Netty中读写以ByteBuf为载体进行交互

ByteBuf的结构

  1. ByteBuf以readerIndex和writerIndex划分为三块区域,废弃字节,可读字节,可写字节。每次从ByteBuf读取一个字节时readerIndex+1,写入一个字节时writerIndex+1。
  2. 废弃字节,这部分的数据是无效的,范围为0~readerIndex-1
  3. 可读字节,从ByteBuf读取的数据都来自这块区域,范围为readerIndex~writerIndex-1,当readerIndex与writerIndex相等时不可读。
  4. 可写字节,写入的数据存放的区域,范围为writerIndex~capacity,当capacity与writerIndex相等时不可写,但是ByteBuf还有一个maxCapacity,容量不足时可以进来扩容,当容量超过maxCapacity时会报错。

读取

	ByteBuf byteBuf = Unpooled.copiedBuffer("hello world".getBytes());
    //判断是否有可读的字节
    System.out.println(byteBuf.isReadable());
    //返回可读字节数
    System.out.println(byteBuf.readableBytes());
    //返回当前的读指针
    System.out.println(byteBuf.readerIndex());
    while (byteBuf.isReadable()) {
        //以read开头的方法都是读取方法,readInt、readBoolean等
        byteBuf.readByte();
    }
    System.out.println(byteBuf.readerIndex());
    //设置读指针
    byteBuf.readerIndex(0);
    //将当前可读数据都读取到byte[]中
    byteBuf.readBytes(new byte[byteBuf.readableBytes()]);

写入

	//分配capacity为9,maxCapacity为12的byteBuf
    ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer(9, 12);
    //返回可写字节数
    System.out.println(byteBuf.writableBytes());
    //判断是否可写
    System.out.println(byteBuf.isWritable());
    //以write开头的都是写入方法
    byteBuf.writeByte(1);
    byteBuf.writeInt(1);
    byteBuf.writeBytes(new byte[]{1,2,3,4});
    //获取写指针
    System.out.println(byteBuf.writerIndex());
    //这时writerIndex==capacity
    System.out.println(byteBuf.writableBytes());
    System.out.println(byteBuf.isWritable());
    //再写入将扩容
    byteBuf.writeByte(1);
    System.out.println(byteBuf.isWritable());
    System.out.println(byteBuf.writableBytes());
    //扩容后仍然不足存放将报错
    //byteBuf.writeInt(1);
    //设置写指针
    byteBuf.writerIndex(0);
    System.out.println(byteBuf.isWritable());
    System.out.println(byteBuf.writableBytes());
    byteBuf.writeInt(1);

引用计数

release() 与 retain()
  1. netty使用的是堆外内存,不被jvm管理,所以需要我们手动释放。
  2. netty使用引用计数管理ByteBuf,如果没有地方引用一个ByteBuf,将直接回收底层内存。
  3. 一个ByteBuf被创建时引用为1,retain()将使引用+1,release()使引用-1,为0时将被回收。
  4. 一般遵循谁retain()(包括创建)谁release()

slice()、duplicate()、copy()

  1. slice()截取可读字节区域返回,新的ByteBuf的maxCapacity为旧的readableBytes(),但底层内存和引用共用
  2. duplicate()为ByteBuf的浅拷贝,读写指针与旧的无关,但底层内存和引用共用
  3. copy()为深拷贝,读写指针、引用和内存都无关
  4. slice()和duplicate()不会增加引用计数,而retainedSlice() 与 retainedDuplicate()会增加计数。

参考资料

Netty实战
Netty 入门与实战:仿写微信 IM 即时通讯系统

posted @ 2019-05-13 00:16  wuweishuo  阅读(1035)  评论(0编辑  收藏  举报