【Netty】 ByteBuf的常用API总结

目录

一、ByteBuf介绍

二、ByteBuf创建

1.池化创建 ByteBufAllocator

2.Unpooled (非池化)创建ByteBuf

3.ByteBufUtil 操作ByteBuf

三、读取ByteBuf数据

1.get方法

2.read方法

3.set方法

4.write方法

5.索引管理 

 6.索引查找

 7.ByteBuf复制

 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类似数组操作,不会改变读索引readIndex,read会改变读索引readIndex。

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 length)读取length字节数,并返回一个新创建的Buf对象,新buf的readIndex=0,writeIndex=length,源buf的readIndex+=length
readBytes(ByteBuf dst)将buf的可读字节写入dst,字节数=min(src.readableBytes,dst.writableBytes),src.readIndex增加,src.writeIndex增加
readBytes(ByteBuf dst, int length)同上,指定长度
readBytes(ByteBuf dst, int dstIndex, int length)同上,但不修改dst.writeIndex
readBytes(byte[] dst)数组版本,也有其他变体
readBytes(ByteBuffer dst)nio buffer版本
readBytes(OutputStream out, int length)ostream版本
readBytes(GatheringByteChannel out, int length)nio channel版本
readCharSequence(int length, Charset charset)字符串版本
readBytes(FileChannel out, long position, int length)文件Channel版本
skipBytes(int length)跳过一些可读字节,readIndex+=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。这不会清除内存中的内容

discardReadBytes抛弃已读字节,将[readerIndex, writeIndex)字节迁移到[0, readableBytes),修改readerIndex=0,writeIndex=readableBytes
discardSomeReadBytes抛弃部分已读字节以节省内存,具体数量由实现来决定,以达到最高效
ensureWritable(int minWritableBytes)按需扩展容量,如果writeIndex+minWritableBytes> maxCapacity,抛出IndexOutOfBoundsException
ensureWritable(int minWritableBytes, boolean force)    
 
功能同上,但不会抛出异常,参数force影响(writeIndex+minWritableBytes> maxCapacity)条件下的行为:force=true,扩充容量至maxCapacity;force=false,不做扩充。返回值只一个反映操作行为的状态码:=0,容量本来就满足,所以未扩充;=1,容量不足,但未扩充;=2,容量已扩充,满足需求;=3,容量以扩充至maxCapacity,但仍未满足需求。

 6.索引查找

方法名称方法描述
bytesBefore(int index, int length, byte value)查询value在buf出现的位置,仅限[index,index+length)区间内查找

for EachByte(ByteBufProcessor.FIND_NUL)

查找byte,返回byte的索引

 7.ByteBuf复制

方法名称方法描述
slice()返回源buf可读字节的一个切片,新buf和源buf共享byte内存,但readIndex,writeIndex互相独立,操作buf不会影响refCnt
duplicate()
retainedDuplicate()
制作buf的一个副本,底层共享byte内存,但readIndex,writeIndex互相独立,操作buf不会影响refCnt
slice(int index, int length)
retainedSlice(int index, int length)
slice变体
retainedSlice()相当于slice().retain()
copy()复制buf的可读字节区,新buf的readIndex=0,新buf和源buf互相独立
copy(int index, int length)新buf的readIndex=0, writeIndex=capacity=length

 8.其他方法

方法名称方法描述
unwrap()如果此对象是包装另一个ByteBuf对象生成的,返回后者,否则返回null
isDirect()是否该ByteBuf是一个直接内存缓冲区
isReadOnly()是否只读
asReadOnly()返回该ByteBuf的一个只读版本
readerIndex(int readerIndex)设置readerIndex,不能<0,或>writerIndex
writerIndex(int writerIndex)设置writerIndex,不能<readerIndex,或> capacity
setIndex(int readerIndex, int writerIndex)同时设置readerIndex, writerIndex
readableBytes()返回可以读的字节长度=writerIndex-readerIndex
isReadable()返回是否有字节可读=(writerIndex-readerIndex>0)
isReadable(size)返回是否有size字节可读=(writerIndex-readerIndex>size)
writableBytes()返回可以写的字节长度=capacity-writerIndex
maxWritableBytes()返回最大可以写的字节长度=maxCapacity-writerIndex

isWritable()

返回是否可以写==(capacity - writerIndex)>0

isWritable(int size)返回是否可以写字节长度size=(capacity - writerIndex)>size
clear()恢复到初始状态,相当于setIndex(0,0)

capacity()

返回byteBuf的容量

maxCapacity()

返回byteBuf可以有的最大容量

hasArray()

buf内部是否被一个byte array支撑

(heap buf才会为true)

array()

返回支撑的byte array,如果不支持,抛出UnsupportedOperationException
arrayOffset()返回buf的0位置,在byte数组中的位置
hasMemoryAddress()buf是否拥有一个指向底层内存的地址
memoryAddress()返回底层内存地址,如果不支持,抛出UnsupportedOperationException
isContiguous()buf是否由一整块内存支持

参考资料

ByteBuf的常用API总结

Netty详解之九:ByteBuf介绍

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NettyBoy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值