天行健,君子以自強不息。
Java NIO 提供了ByteBuffer 作爲它的字節容器,但是這個類使⽤起來過於複雜,⽽且也有些繁瑣。Netty 的 ByteBuffer 替代品是 ByteBuf,⼀個強⼤的實現,既解決了JDK API 的侷限性,⼜爲⽹絡應⽤程序的開發者提供了更好的API。
從結構上來說,ByteBuf 由⼀串字節數組構成。數組中每個字節⽤來存放信息。
ByteBuf 提供了兩個索引,⼀個⽤於讀取數據,⼀個⽤於寫⼊數據。這兩個索引通過在字節數組中移動,來定位需要讀或者寫信息的位置。
當從 ByteBuf 讀取時,它的 readerIndex(讀索引)將會根據讀取的字節數遞增。
同樣,當寫 ByteBuf 時,它的 writerIndex(寫索引)也會根據寫⼊的字節數進⾏遞增。
如果 readerIndex 超過了 writerIndex 的時候,Netty 會拋出 IndexOutOf-BoundsException 異常。
ByteBuf的讀取操作
package cn.lyy.myrcp.server.cn.lyy.test; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.util.CharsetUtil; public class ByteBufTest01 { public static void main(String[] args) { ByteBuf byteBuf = Unpooled.copiedBuffer("hello liuyuanyuan,hello World", CharsetUtil.UTF_8); System.out.println("byteBuf的容量爲: "+byteBuf.capacity()); System.out.println("byteBuf的可讀容量爲: "+ byteBuf.readableBytes()); System.out.println("byteBuf的可寫容量爲: "+byteBuf.writableBytes()); //方法一內部通過移動readIndex進行讀取 while(byteBuf.isReadable()){ System.out.print((char) byteBuf.readByte()); } } }
其他2種讀取方法
package cn.lyy.myrcp.server.cn.lyy.test; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.util.CharsetUtil; public class ByteBufTest01 { public static void main(String[] args) { ByteBuf byteBuf = Unpooled.copiedBuffer("hello liuyuanyuan,hello World", CharsetUtil.UTF_8); System.out.println("byteBuf的容量爲: "+byteBuf.capacity()); System.out.println("byteBuf的可讀容量爲: "+ byteBuf.readableBytes()); System.out.println("byteBuf的可寫容量爲: "+byteBuf.writableBytes()); /*//方法一內部通過移動readIndex進行讀取 while(byteBuf.isReadable()){ System.out.print((char) byteBuf.readByte()); }*/ /*//⽅法⼆:通過下標直接讀取 for (int i=0; i< byteBuf.readableBytes() ; i++ ) { System.out.print((char)byteBuf.getByte(i)); }*/ // ⽅法三:轉化爲byte[]進⾏讀取 byte[] bytes = byteBuf.array(); for (byte b : bytes) { System.out.print((char)b); } } }
寫入操作
package cn.lyy.myrcp.server.cn.lyy.test; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; public class ByteBufTest02 { public static void main(String[] args) { //構造空的字節緩衝區,初始⼤⼩爲10,最⼤爲20 ByteBuf byteBuf= Unpooled.buffer(10,20); System.out.println("byteBuf的容量爲:"+byteBuf.capacity()); System.out.println("byteBuf的可讀容量爲:"+byteBuf.readableBytes()); System.out.println("byteBuf的可寫容量爲:"+byteBuf.writableBytes()); for (int i=0; i<5; i++) { byteBuf.writeInt(i); //寫⼊int類型,⼀個int佔4個字節 } System.out.println("ok"); System.out.println("byteBuf的容量爲:"+byteBuf.capacity()); System.out.println("byteBuf的可讀容量爲:"+byteBuf.readableBytes()); System.out.println("byteBuf的可寫容量爲:"+byteBuf.writableBytes()); while (byteBuf.isReadable()) { System.out.print(byteBuf.readInt()); } } }
⼊站處理流程中,如果對原消息不做處理,調⽤ ctx.fireChannelRead(msg) 把原消息往下傳,由流⽔線最後⼀棒 TailHandler 完成⾃動釋放。
如果截斷了⼊站處理流⽔線,則可以繼承 SimpleChannelInboundHandler ,完成⼊站ByteBuf ⾃動釋放。出站處理過程中,申請分配到的 ByteBuf,通過 HeadHandler 完成⾃動釋放。
⼊站處理中,如果將原消息轉化爲新的消息並調⽤ ctx.fireChannelRead(newMsg)往下傳,那必須 把原消息release掉;
⼊站處理中,如果已經不再調⽤ ctx.fireChannelRead(msg) 傳遞任何消息,也沒有繼承SimpleChannelInboundHandler 完成⾃動釋放,那更要把原消息release掉;