Netty 學習筆記(2) ------ 數據傳輸載體ByteBuf
阿新 • • 發佈:2019-05-13
lean 增加 print [] 拷貝 ase 實戰 pri 參考資料
Netty中讀寫以ByteBuf為載體進行交互
ByteBuf的結構
- ByteBuf以readerIndex和writerIndex劃分為三塊區域,廢棄字節,可讀字節,可寫字節。每次從ByteBuf讀取一個字節時readerIndex+1,寫入一個字節時writerIndex+1。
- 廢棄字節,這部分的數據是無效的,範圍為0~readerIndex-1
- 可讀字節,從ByteBuf讀取的數據都來自這塊區域,範圍為readerIndex~writerIndex-1,當readerIndex與writerIndex相等時不可讀。
- 可寫字節,寫入的數據存放的區域,範圍為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()
- netty使用的是堆外內存,不被jvm管理,所以需要我們手動釋放。
- netty使用引用計數管理ByteBuf,如果沒有地方引用一個ByteBuf,將直接回收底層內存。
- 一個ByteBuf被創建時引用為1,retain()將使引用+1,release()使引用-1,為0時將被回收。
- 一般遵循誰retain()(包括創建)誰release()
slice()、duplicate()、copy()
- slice()截取可讀字節區域返回,新的ByteBuf的maxCapacity為舊的readableBytes(),但底層內存和引用共用
- duplicate()為ByteBuf的淺拷貝,讀寫指針與舊的無關,但底層內存和引用共用
- copy()為深拷貝,讀寫指針、引用和內存都無關
- slice()和duplicate()不會增加引用計數,而retainedSlice() 與 retainedDuplicate()會增加計數。
參考資料
Netty實戰
Netty 入門與實戰:仿寫微信 IM 即時通訊系統
Netty 學習筆記(2) ------ 數據傳輸載體ByteBuf