ByteBuf的分配
一. ByteBufAllocator 池类
可分配基于堆的或者直接内存的ByteBuf
获得ByteBufAllocator引用的的两种方式:
channel.alloc();
ctx.alloc();
ByteBufAllocator的两种实现:
PooledByteBufAllocator
UnpooledByteBufAllocator
二.Unpooled 非池化的Bytebuf
三.ByteBufUtil
ByteBuf 和 ByteBufHolder
ByteBuf的主要有读写两个指针,这是他比原生ByteBuffer方便和易于理解的地方
read*, write*开头的方法会改变索引,但是set*将不会改变索引位置
|**** 版本号 4个字节的长度 具体的内容****|
ByteBuf 的使用模式
1. 堆缓冲区(基于数组实现的)
所以可以通过hasArray判断是否支持数组
ByteBuf heapBuf = ...; if (heapBuf.hasArray()) { //1 byte[] array = heapBuf.array(); //2 int offset = heapBuf.arrayOffset() + heapBuf.readerIndex(); //3 int length = heapBuf.readableBytes();//4 handleArray(array, offset, length); //5 }
2. 直接缓冲区
ByteBuf directBuf = ... if (!directBuf.hasArray()) { //1 int length = directBuf.readableBytes();//2 byte[] array = new byte[length]; //3 directBuf.getBytes(directBuf.readerIndex(), array); //4 handleArray(array, 0, length); //5 }
3. 复合缓冲区(CompositeByteBuf )
hasArray始终返回false
CompositeByteBuf messageBuf = ...; ByteBuf headerBuf = ...; // 可以支持或直接 ByteBuf bodyBuf = ...; // 可以支持或直接 messageBuf.addComponents(headerBuf, bodyBuf); // .... messageBuf.removeComponent(0); // 移除头 //2 for (int i = 0; i < messageBuf.numComponents(); i++) { //3 System.out.println(messageBuf.component(i).toString()); }
访问数据
CompositeByteBuf compBuf = ...; int length = compBuf.readableBytes(); //1 byte[] array = new byte[length]; //2 compBuf.getBytes(compBuf.readerIndex(), array); //3 handleArray(array, 0, length); //4
随机访问索引:
如getByte,不会改变索引
可丢弃的字节重新利用:
iscardReadBytes();
索引操作:
markWriterIndex()
markReaderIndex()
resetReaderIndex()
resetWriterIndex()
clear() 比 discardReadBytes()成本更低
查询操作:
forEachByte
int index = buffer.forEachByte(ByteBufProcessor.FIND_CR);
forEachByte(ByteBufProcessor.FIND_NUL)
衍生的缓冲区:
代表一个专门的展示 ByteBuf 内容的“视图"
这种视图由下面几种方法产生
duplicate(), slice(), slice(int, int),readOnly(),order(ByteOrder)
这种视图和源是数据共享的吗? 读写索引是一样的吗? 标记索引是一样的吗?
答:都是共享的
拷贝:
copy()和copy(int, int)
这个副本是独立的, 和源数据不共享
需要某段数据:
slice(int, int)
和源数据是共享的
读写操作:
set写入/get读取不会改变索引
write/read