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 即時通信系統jvm

相關文章
相關標籤/搜索