长春免费做网站做热点链接的网站
目录
一、ByteBuf介绍
二、ByteBuf创建
1.池化创建 ByteBufAllocator
2.Unpooled (非池化)创建ByteBuf
3.ByteBufUtil 操作ByteBuf
三、读取ByteBuf数据
1.get方法
2.read方法
3.set方法
4.write方法
5.索引管理
6.索引查找
7.索引查找
8.其他方法
本篇主要介绍ByteBuf的常用操作API,Netty性能的卓越表现离不开ByteBuf的巧妙设计,它提供了一系列的缓冲区读写方法,另外为了方便起见还特定义了ByteBufUtil,提供了比较丰富的操作ByteBuf方法。
一、ByteBuf介绍
 为了提高性能,Netty重新设计了字节缓冲区ByteBuf,类似Java Nio的ByteBuffer,但工作方式略有区别,比后者更加灵活、高效。
ByteBuf有几个重要属性:
capacity:容量;
 0:缓冲区开始位置;
 readIndex:下一个读位置;
 writeIndex:下一个写位置;
 一个ByteBuf对象即可像byte数组一样工作,又可以像IO字节流一样工作。当前的可读数据区是[readIndex,writeIndex);可写区是[writeIndex,capacity);而[0,readIndex)区间的字节是可废弃数据(Discardable),如下图所示:
+-------------------+------------------+------------------+  
| discardable bytes |  readable bytes  |  writable bytes  |  
|                   |     (CONTENT)    |                  |  
+-------------------+------------------+------------------+  
|                   |                  |                  |  
0      <=      readerIndex   <=   writerIndex    <=    capacity
 
基本的操作包括
1.从ByteBuf中读取数据,从readerIndex开始向后读取需要的字节数,readerIndex随之改变;
2.向ByteBuf中写数据,从writeIndex开始向后写数据,同时writeIndex随之改变;
3.删除ByteBuf已读数据,从[0,readerIndex)为已读完的数据,为了节省空间需要释放内存,释放示意图如下:
*  BEFORE discardReadBytes()**      +-------------------+------------------+------------------+*      | discardable bytes |  readable bytes  |  writable bytes  |*      +-------------------+------------------+------------------+*      |                   |                  |                  |*      0      <=      readerIndex   <=   writerIndex    <=    capacity***  AFTER discardReadBytes()**      +------------------+--------------------------------------+*      |  readable bytes  |    writable bytes (got more space)   |*      +------------------+--------------------------------------+*      |                  |                                      |* readerIndex (0) <= writerIndex (decreased)        <=        capacity 
4.清空ByteBuf数据,不需要清空数据,通过移动两个指针readerIndex和writeIndex,指向0即可。
*  BEFORE clear()**      +-------------------+------------------+------------------+*      | discardable bytes |  readable bytes  |  writable bytes  |*      +-------------------+------------------+------------------+*      |                   |                  |                  |*      0      <=      readerIndex   <=   writerIndex    <=    capacity***  AFTER clear()**      +---------------------------------------------------------+*      |             writable bytes (got more space)             |*      +---------------------------------------------------------+*      |                                                         |*      0 = readerIndex = writerIndex            <=            capacity 
二、ByteBuf创建
1.池化创建 ByteBufAllocator
即PooledByteBufAllocator
获取ByteBufAllocator,通过以下两种方式获取
//方法1
Channel channel = ...;
ByteBufAllocator allocator = channel.alloc();  
//方法2
ChannelHandlerContext ctx = ...;
ByteBufAllocator allocator2 = ctx.alloc();  
 
ByteBufAllocator中创建byteBuf的方法如下
| 方法名称 | 方法描述 | 
|   buffer() buffer(int) buffer(int, int)  | Return a ByteBuf with heap-based or direct data storage | 
|   heapBuffer() heapBuffer(int) heapBuffer(int, int)  |   Return a ByteBuf with heap-based storage.  | 
|   directBuffer() directBuffer(int) directBuffer(int, int)  |   Return a ByteBuf with direct storage.  | 
|   compositeBuffer() compositeBuffer(int) heapCompositeBuffer() heapCompositeBuffer(int) directCompositeBuffer() directCompositeBuffer(int)   | Return a CompositeByteBuf that can be expanded by adding heapbased or direct buffers. | 
|   ioBuffer()  |   Return a ByteBuf that will be used for I/O operations on a socket.  | 
2.Unpooled (非池化)创建ByteBuf
即UnPooledByteBufAllocator
当未引用 ByteBufAllocator 时,上面的方法无法访问到 ByteBuf。对于这个用例 Netty 提供一个实用工具类称为 Unpooled,,它提供了静态辅助方法来创建非池化的 ByteBuf 实例,方法如下:
| 方法名称 | 方法描述 | 
|   buffer() buffer(int) buffer(int, int)  | Returns an unpooled ByteBuf with heap-based storage | 
|   directBuffer() directBuffer(int) directBuffer(int, int)  | Returns an unpooled ByteBuf with direct storage | 
|   wrappedBuffer()  |   Returns a ByteBuf, which wraps the given data.  | 
|   copiedBuffer()  |   Returns a ByteBuf, which copies the given data  | 
3.ByteBufUtil 操作ByteBuf
三、读取ByteBuf数据
get/read get不会改变读索引,read会改变读索引
1.get方法
| 方法名称 | 方法描述 | 
|   getBoolean(int)  |   返回当前索引的 Boolean 值  | 
|   getByte(int) getUnsignedByte(int)  |   返回当前索引的(无符号)字节  | 
|   getMedium(int) getUnsignedMedium(int)  |   返回当前索引的 (无符号) 24-bit 中间值  | 
|   getInt(int) getUnsignedInt(int)  |   返回当前索引的(无符号) 整型  | 
|   getLong(int) getUnsignedLong(int)  |   返回当前索引的 (无符号) Long 型  | 
|   getShort(int) getUnsignedShort(int)  |   返回当前索引的 (无符号) Short 型  | 
|   getBytes(int, ...)  |   字节  | 
2.read方法
| 方法名称 | 方法描述 | 
|   readBoolean()  |   返回当前索引的Boolean值,读索引加一  | 
|   readByte() readUnsignedByte()  |   返回当前索引的(无符号)字节,读索引加一  | 
|   readMedium() readUnsignedMedium()  |   返回当前索引的 (无符号) 24-bit 中间值,读索引加3  | 
|   readInt() readUnsignedInt()  |   返回当前索引的(无符号) 整型,读索引加4  | 
|   readLong() readUnsignedLong()  |   返回当前索引的 (无符号) Long 型,读索引加8  | 
|   readShort() readUnsignedShort()  |   返回当前索引的 (无符号) Short 型,读索引加2  | 
|   readBytes(int,int, ...)  |   返回当前位置到length得到一个字节数组,读索引加length  | 
3.set方法
| 方法名称 | 方法描述 | 
|   setBoolean(int, boolean)  |   在指定的索引位置设置 Boolean 值  | 
|   setByte(int, int)  |   在指定的索引位置设置 byte 值  | 
|   setMedium(int, int)  |   在指定的索引位置设置 24-bit 中间 值  | 
|   setInt(int, int)  |   在指定的索引位置设置 int 值  | 
|   setLong(int, long)  |   在指定的索引位置设置 long 值  | 
|   setShort(int, int)  |   在指定的索引位置设置 short 值  | 
4.write方法
| 方法名称 | 方法描述 | 
|   writeBoolean(boolean)  |   在指定的索引位置设置 Boolean 值,写索引加一  | 
|   writeByte(int)  |   在指定的索引位置设置 byte 值,写索引加一  | 
|   writeMedium(int)  |   在指定的索引位置设置 24-bit 中间 值,写索引加3  | 
|   writeInt(int)  |   在指定的索引位置设置 int 值,写索引加4  | 
|   writeLong(long)  |   在指定的索引位置设置 long 值,写索引加8  | 
|   writeShort(int)  |   在指定的索引位置设置 short 值,写索引加2  | 
|   writeBytes(int,...)  |   在当前索引写入一个Byte数组,写索引加数组长度  | 
5.索引管理
| 方法名称 | 方法描述 | 
|   markReaderIndex(), markWriterIndex()  |   标记读(写)索引  | 
|   resetReaderIndex() resetWriterIndex()  |   读(写)索引回到mark标记的索引值  | 
|   readerIndex(int) writerIndex(int)  |   将读(写)索引设置到指定位置  | 
|   clear()  |   可以同时设置 readerIndex 和 writerIndex 为 0。这不会清除内存中的内容  | 
6.索引查找
| 方法名称 | 方法描述 | 
|   for EachByte(ByteBufProcessor.FIND_NUL)  |   查找byte,返回byte的索引  | 
7.索引查找
| 方法名称 | 方法描述 | 
|   duplicate()  slice(int, int)   | 所有这些都返回一个新的 ByteBuf 实例包括它自己的 reader, writer 和标记索引。然而,内部数据存储共享就像在一个 NIO 的 ByteBuffer | 
|   copy() copy(int, int)  |   返回的 ByteBuf 有数据的独立副本  | 
8.其他方法
| 方法名称 | 方法描述 | 
|   isReadable()  |   返回是否有字节可读  | 
|   isWritable()  |   返回是否可以写  | 
|   readableBytes()  |   返回可以读的字节长度  | 
|   writablesBytes()  |   返回可以写的字节长度  | 
|   capacity()  |   返回byteBuf的容量  | 
|   maxCapacity()  |   返回byteBuf可以有的最大容量  | 
|   hasArray()  |   如果byteBuf可以直接返回一个数组就返回true (heap buf才会为true)  | 
|   array()  |   hasArray返回true,该方法就会返回一个数组  | 
参考资料
ByteBuf的常用API总结
Netty详解之九:ByteBuf介绍
