ByteBuf是Netty框架里最重要的类之一,简单的说,ByteBuf就是Java.nio.ByteBuffer的Netty版。
ByteBuf逻辑结构
正如类名所反映出来的,ByteBuf逻辑上就是一个byte容器。ByteBuf里的数据被两个指针划分为三个部分,如下图所示:
- reader index前面的数据是已经读过的数据,这些数据可以扔掉
- 从reader index开始,到writer index之前的数据是可读数据
- 从writer index开始,为可写区域
正是因为这样的设计,ByteBuf可以同时读写数据(只要可读区域和可写区域都还有空闲空间),而java.nio.ByteBuffer则必须调用flip()方法才能从写状态切换到读状态。
ByteBuf API
ByteBuf提供了大量的方法,比较常用的有下面这些:
- writeXxx(xxx value) 这组方法将不同类型的数据写到buf里,同时将writerIndex往前移适当的距离
- readXxx() 这组方法从buf里读出某种类型的数据,同时将readerIndex往前移适当的距离
- skipBytes(int length) 将readerIndex往前移指定的距离
- setXxx(int index, xxx value) 这组方法将不同类型的数据写到buf的指定位置
- getXxx(int index) 这组方法从buf的指定位置读出一个某种类型的数据
- readerIndex()/writerIndex() 访问readerIndex和writerIndex
- readerIndex(int)/writerIndex(int) 设置readerIndex和writerIndex
- readableBytes() 返回可读区域的字节数
- writableBytes() 返回可写区域的字节数
- clear() 清除buf(把readerIndex和writerIndex都设为0)
- discardReadBytes() 扔掉已读数据
值得一提的是,discardReadBytes()方法需要把可读数据移动到buf的开头,因此是个比较慢的操作。而clear()方法只是将两个指针清0,所以相对而言速度很快。
ByteBufAllocator - 抽象工厂模式
在Netty的世界里,ByteBuf实例通常应该由ByteBufAllocator来创建。ByteBuf和Allocator的关系如下图所示:
Allocator的buffer()方法创建ByteBuf实例,ByteBuf的alloc()方法返回创建自己的Allocator。ByteBufAllocator的实现使用了抽象工厂模式,如下图所示:
CompositeByteBuf - 组合模式
CompositeByteBuf可以让我们把多个ByteBuf当成一个大Buf来处理,ByteBufAllocator提供了compositeBuffer()工厂方法来创建CompositeByteBuf。CompositeByteBuf的实现使用了组合模式,如下图所示:
ByteBufInputStream - 适配器模式
ByteBufInputStream使用适配器模式,使我们可以把ByteBuf当做Java的InputStream来使用。同理,ByteBufOutputStream允许我们把ByteBuf当做OutputStream来使用。
比如说我们要实现一个自定义的消息协议,消息包括header和body两部分内容,body里放的是JSON字符串。那么就可以使用ByteBufInputStream来避免把ByteBuf里的字节拷贝到字节数组的开销:
- private Object decodeMessage(ByteBuf bb) {
- // read header
- // bb.readXxx()...
- // read body
- InputStreamReader reader = new InputStreamReader(new ByteBufInputStream(bb));
- return new Gson().fromJson(reader, JsonObject.class);
- }
ReadOnlyByteBuf - 装饰器模式
ReadOnlyByteBuf用适配器模式把一个ByteBuf变为只读,ReadOnlyByteBuf通过调用Unpooled.unmodifiableBuffer(ByteBuf)方法获得:
类似的ByteBuf适配器还包括:
ByteBuf - 工厂方法模式
前面也提到过了,我们很少需要直接通过构造函数来创建ByteBuf实例,而是通过Allocator来创建。从装饰器模式可以看出另外一种获得ByteBuf的方式是调用ByteBuf的工厂方法,比如:
- ByteBuf#duplicate()
- ByteBuf#slice()
ByteBufProcessor - 访问者模式还是迭代器模式?
最后,ByteBuf提供了4个forEachByte()方法来对ByteBuf里的数据进行某种处理或查找,看起来像是访问者模式和迭代器模式的混合:
- public abstract int forEachByte(ByteBufProcessor processor);
- public abstract int forEachByte(int index, int length, ByteBufProcessor processor);
- public abstract int forEachByteDesc(ByteBufProcessor processor);
- public abstract int forEachByteDesc(int index, int length, ByteBufProcessor processor);
相关推荐
仿安卓ByteBuffer 完美组包、拆包
使用nio byteBuffer 实现按行读取文件(大文件) 在window/linux/macOS上均测试通过 对于中文乱码也已处理成功 完整注释,可随需求更改 有问题请邮件:mly610865580@126.com
Android
主要解决从流中获取数据,缓存,拆解,可用于TCP粘包问题
【IT十八掌徐培成】Java基础第26天-05.ByteBuffer-mark-pos-limit-cap-flip.zip
易语言汇编版ByteBuffer源码。主要用于各种网络协议的组包 具体用法可以点上面的网址 功能和jAVA的一样。@10371178。Tags:易语言汇编版ByteBuffer源码。
本文实例讲述了Android在JNI中使用ByteBuffer的方法。分享给大家供大家参考。具体如下: 一、ByteBuffer 定义 在NIO中,数据的读写操作始终是与缓冲区相关联的(读取时信道(SocketChannel)将数据读入缓冲区,写入时...
protobuf+long+bytebuffer,利用protobuf.js实现编解码 所需的三个js库
易语言汇编版ByteBuffer源码主要用于各种网络协议的组包 具体用法可以点上面的网址 功能和jAVA的一样
ios-byteBuffer [![CI状态]( Lee / ios-byteBuffer.svg?style = flat)]( Lee / ios-byteBuffer ) 用法 #分配 ByteBuffer *buffer = [ByteBuffer initWithOrder: ByteOrderLittleEndian]; #输入数据 - ( ...
java api之ByteBuffer基础、应用场景、实战讲解 文档中有丰富的例子代码实现
dena-bytebuffer
jdk api-ServerSocketChannel、Selector、ByteBuffer结合实现网络报文间的通讯
NULL 博文链接:https://chinaestone.iteye.com/blog/468138
NULL 博文链接:https://zheng12tian.iteye.com/blog/1094811
支持任意读取/写入,隐式增长,剪切,克隆和反转以及UTF-8字符和以NULL结尾的C字符串。 安装 ByteBuffer可通过: npm install byte-buffer 或在浏览器中使用: dist/byte-buffer.js dist/byte-buffer.min.js ...
├─(2) 第1章_02_nio三大组件-服务器设计-多线程版.mp4 ├─(3) 第1章_03_nio三大组件-服务器设计-线程池版.mp4 ├─(4) 第1章_04_nio三大组件-服务器设计-selector版.mp4 ├─(5) 第1章_05_bytebuffer-基本使用....
phpuse PHPinnacle \ Buffer \ ByteBuffer ;// AMQP protocol header$ buffer = new ByteBuffer ;$ buffer -> append ( 'AMQP' ) -> appendUint8 ( 0 ) -> appendUint8 ( 0 ) -> appendUint8 ( 9 ) -> appendUint8 ...