Netty-ByteBuf

ByteBuf的优点

  • 它可以被用户自定义的缓冲区类型扩展;
  • 通过内置的复合缓冲区实现了透明的零拷贝;
  • 容量可以按需增长(类似于JDK的StrigBuilder);
  • 在读和写这两种模式切换不需要调用ByteBuffer的filp()方法;
  • 读和写使用了不同的索引
  • 支持方法的链式调用
  • 支持引用计数;
  • 支持池化。

ByteBuf类——Netty的数据容器

ButeBuf维护了两个不同的索引:一个用于读取,一个用于写入。

名称read和write开头的ByteBuf方法,将会推进其对应的索引,而名称以set或者get开头的操作则不会。

堆缓冲区

最常用的ByteBuf模式是将数据存储在JVM的堆内存空间,这种模式被称为支撑数组,它能在没有使用池化的情况下提供快速的分配和释放。

1
2
3
4
5
6
7
ByteBuf heapBuf = ...;
if(heapBuf.hasArray()){
byte []array = heapBuf.array();
int offset = heapBuf.arrayOffset() + heapBuf.readerIndex(); //计算第一个字节的偏移量
int length = heapBuf.readableBytes(); //获得可读字节数
handleArray(array, offset, length); //逻辑处理array
}

直接缓冲区

直接缓冲区是另外一种ByteBuf模式。直接缓冲区的内容将驻留在常规的会被垃圾回收的堆之外。直接缓冲区对于网络数据传输是理想的选择。如果数据包含在一个堆上分配的缓冲区中,那么事实上,在通过套接字发送之前,JVM将会在内部把缓冲区复制到一个直接缓冲区。

1
2
3
4
5
6
7
ByteBuf directBuf = ...;
if(!directBuf.hasArray){ //非支撑数组,则为直接缓冲区
int length = directBuf.readableBytes();
byte []array = new byte[length];
directBuf.getBytes(directBuf.readerIndex(), array); //将字节复制到array
handle(array, 0, length);
}

复合缓冲区

复合缓冲区为多个ByteBuf提供一个聚合视图。在这里可以根据需要添加或者删除ByteBuf实例。

点击加载

1
2
3
4
CompositeByteBuf buf = Unpooled.compositeBuffer();
ByteBuf headBuf = ...; //堆缓冲区或者直接缓冲区
ByteBuf bodyBuf = ...; //同上
buf.addComponents(headBuf, bodyBuf);