1. 程式人生 > >Netty 學習筆記(2) ------ 數據傳輸載體ByteBuf

Netty 學習筆記(2) ------ 數據傳輸載體ByteBuf

lean 增加 print [] 拷貝 ase 實戰 pri 參考資料

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

Netty 學習筆記(2) ------ 數據傳輸載體ByteBuf