跳转到内容


Netty 5.0 ByteBuf 详解

netty

  • 您无法回复此主题
No replies to this topic

#1 冰力

    Administrator

  • 总版主
  • 1315 帖子数:

发表于 2016/01/20 01:08:08

本文主要介绍Netty 5.0 ByteBuf原理及具体使用。

基本结构:与NIO ByteBuffer类似,使用ByteBuffer往往需要在读写之间通过flip切换。ByteBuf里维护两个index,一个readerIndex,一个writerIndex;readerIndex writerIndex capactiy 的三者的关系是:
0 <=readerIndex <=writerIndex <= capacity
当往byteBuf写入一个byte时,writerIndex++,从bytebuf读一个byte时,readerIndex++;

+-------------------+------------------+------------------+
| discardable bytes |  readable bytes  |  writable bytes  |
|				   |	 (CONTENT)    |				  |
+-------------------+------------------+------------------+
|				   |				  |				  |
0	  <=	  readerIndex   <=   writerIndex    <=    capacity

基本操作:
通过index随机读:
ByteBuf byteBuf= Unpooled.buffer();
byteBuf.writeBytes("hello world".getBytes());
System.out.println((char)byteBuf.getByte(0));
System.out.println((char)byteBuf.getByte(1));

支持顺序读:满足readeableBytes>0 (writerIndex - readerIndex )

ByteBuf byteBuf= Unpooled.buffer();
byteBuf.writeBytes("hello world".getBytes());
while(byteBuf.readableBytes()>0)
{
	System.out.println((char)byteBuf.readByte());
}
写操作:
支持单个byte写入,或者直接写入byte数组;可以通过writeIndex设定writerIndex,但是如果
writerIndex < readerIndex || writerIndex > capacity() 会抛出IndexOutOfBoundsException;
ByteBuf byteBuf= Unpooled.buffer(50);
while(byteBuf.writableBytes()>10)
{
	byteBuf.writeByte('a');
	byteBuf.writerIndex(byteBuf.writerIndex()+10);
}
System.out.println("writerIndex:"+byteBuf.writerIndex());
System.out.println("readerIndex:"+byteBuf.readerIndex());
System.out.println("index of 0 is:"+(char)byteBuf.getByte(0));
System.out.println("index of 11 is:"+(char)byteBuf.getByte(11));
System.out.println("index of 22 is:"+(char)byteBuf.getByte(22));
System.out.println("index of 33 is:"+(char)byteBuf.getByte(33));
System.out.println("index of 40 is:"+(char)byteBuf.getByte(40));
System.out.println(new String(byteBuf.array()));


discardReadBytes操作:
把bytebuf中读过的byte抛弃掉,writerIndex置为writerIndex-readerIndex,readerIndex置为0;
ByteBuf byteBuf= Unpooled.buffer();
byteBuf.writeBytes("hello world".getBytes());
System.out.println("readerIndex:" + byteBuf.readerIndex());
System.out.println("writerIndex:" + byteBuf.writerIndex());
System.out.println((char)byteBuf.readByte());
System.out.println(new String(byteBuf.array()));
byteBuf.discardReadBytes();
System.out.println("readerIndex:" + byteBuf.readerIndex());
System.out.println("writerIndex:" + byteBuf.writerIndex());
System.out.println(new String(byteBuf.array()));

clear mark reset 操作:
clear把bytebuf 的writerIndex=readerindex=0;
mark把当前的writerIndex或者readerIndex mark一下,记录到私有变量中
reset把当前的writerIndex或者readerIndex恢复到mark的index;

ByteBuf byteBuf= Unpooled.buffer();
byteBuf.writeBytes("hello world".getBytes());
System.out.println(new String(byteBuf.array()));
System.out.println("readerIndex:" + byteBuf.readerIndex());
System.out.println("writerIndex:" + byteBuf.writerIndex());
byteBuf.clear();
System.out.println("after clear");
System.out.println("readerIndex:" + byteBuf.readerIndex());
System.out.println("writerIndex:" + byteBuf.writerIndex());
System.out.println(new String(byteBuf.array()));
byteBuf.writerIndex(11);

byteBuf.readByte();
//在index 为1时mark ,reset之后重新回到mark的地方	    
byteBuf.markReaderIndex();
byteBuf.readByte();
byteBuf.readByte();
byteBuf.resetReaderIndex();
System.out.println("readerIndex:" + byteBuf.readerIndex());

Netty中分配ByteBuf有两种方式,一个是Pooled 池化的,一个是Unpooled 非池化的。
Unpooled类封装了UnpooledByteBufAllocator,用来初始化ByteBuf 包含Heap类型和Direct类型的。
PooledByteBufAllocator用来分配池化的ByteBuf,重复利用ByteBuf数组,减少分配回收开销。
同时Buffer模块还提供方便的工具类ByteBufUtil来操作ByteBuf。