Netty之ByteBuf

1--ByteBuf的API的优点

》可以被用户自定义的缓冲区类型扩展

》通过内置的复合缓冲区类型实现了透明的零拷贝

》容量可以按需增长

》在读和写这两种模式间切换不需要调用ByteBuffer的flip()方法

》读和写分别使用了readerIndex和writerIndex两个索引

》支持方法的链式调用

》支持引用计数

》支持池化技术

2--ByteBuf的使用模式

(a)堆缓冲区

(b)直接缓冲区

(c)复合缓冲区

============================堆缓冲区=================

最常用的ByteBuf模式是将数据存储在JVM的堆空间,这种模式能够在没有使用池化的情况下提供快速的分配和释放,如下代码。

ByteBuf heapBuf=...;

if(heapBuf.hasArray()){//检查ByteBuf缓冲是否有一个内部数组---若返回false则触发不支持操作异常

  byte[] array=heapBuf.array();

  int offset=heapBuf.arrayOffset()+heapBuf.readerIndex();//计算第一个字节的偏移量

  int len=heapBuf.readableBytes();

  handleArray(array,offset,len);//自定义的方法调用数组、偏移量、长度参数来处理

}

======================直接缓冲区=================

  1》直接缓冲区的内容将驻留在常规的会被垃圾回收的堆之外。直接缓冲区对于网络数据传输是理想的选择。

如果你的数据包含在一个在堆上分配的缓冲区中,实际上在通过套接字发送它之前,JVM将会在内部把你的

缓冲区复制到一个直接缓冲区。

  2》直接缓冲区的主要缺点:相对于堆缓冲区而言,直接缓冲的的分配释放比较昂贵。如果你正在处理遗留代码

可能会遇到一个问题,由于数据不在堆上,所以需要进行复制,如下代码。

ByteBuf directBuf=...;

if(!directBuf.hasArray()){//不是堆缓冲,则是一个直接缓冲

  int len=directBuf.readableBytes();//获取可读字节数

  byte[] arr=new byte[len];

  directBuf.getBytes(directBuf.readerIndex(),arr);//将字节复制到数组arr

  handArr(arr,0,len);//自己的方法

}

================复合缓冲区======

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

Netty通过一个ByteBuf子类CompositeByteBuf(可能同时包含直接内存分配和非直接内存分配)实现了复合缓冲区,

它提供了一个将多个缓冲区表示为单个合并缓冲区的虚拟表示。

CompositeByteBuf cbuf=Unpooled.compositeBuffer();

ByteBuf buf1=...;

ByteBuf buf2=...;

 cbuf.addComponents(buf1,buf2);//将两个缓冲组件添加到复合缓冲区

 

cbuf.removeComponents(0);//删除位于第一个位置的缓冲

for(ByteBuf buf:cbuf){

  System.out.println(buf.toString());

}

==============字节级别的操作==========

1》随机访问索引

ByteBuf buf=...;

for(int i=0;i<buf.capacity();i++){

  byte b=buf.getByte(i);

  System.out.println((char)b);

}

注:使用那些需要一个索引值参数的方法之一来访问数据既不会改变readerIndex也不会改变writerIndex.

通过readerIndex(index)或者writerInder(index)可以改变索引值

2》顺序访问索引

 

posted @ 2017-12-25 17:01  Bruce-Lee  阅读(525)  评论(0编辑  收藏  举报