Netty入门(一):ByteBuf
网络数据的基本单位总是字节。Java NIO 提供了 ByteBuffer 作为它的字节容器,但是这个类使用起来过于复杂,而且也有些繁琐。Netty 的 ByteBuffer 替代品是 ByteBuf,一个强大的实现,既解决了 JDK API 的局限性,又为网络应用程序的开发者提供了更好的 API
ByteBuf优势
- 它可以被用户自定义的缓冲区类型扩展
- 通过内置的复合缓冲区类型实现了透明的零拷贝
- 容量可以按需增长
- 在读和写这两种模式之间切换不需要调用 ByteBuffer 的 flip()方法
- 读和写使用了不同的索引
- 支持方法的链式调用
- 支持引用计数
- 支持池化
ByteBuf实现原理

如图ByteBuf通维护了两个不同的索引:一个用于读取,一个用于写入。
当你从 ByteBuf 读取时,它的 readerIndex 将会被递增已经被读取的字节数。同样地,当你写入 ByteBuf 时,它的writerIndex 也会被递增

当调用readBytes时,readIndex会相应移动length位,如果readIndex移动后大于writeIndex则会抛异常。

当调用writeBytes时,writeIndex会相应移动length位,且通过ensureWritable方法实现自动扩容
其他常用API
| getBytes | 获取可读字节数组 |
| setBytes | 写入字节 |
| discardReadBytes | 废弃已读字节 |
| mark | 标记index |
| reset | 将index重置到之前标记的位置(配合mark使用) |
| isReadable | 如果至少有一个字节可供读取,则返回 true |
| isWritable | 如果至少有一个字节可被写入,则返回 true |
| readableBytes | 返回可被读取的字节数 |
| writableBytes | 返回可被写入的字节数 |
| capacity | 返回 ByteBuf 可容纳的字节数。在此之后,它会尝试再次扩展直到达到 maxCapacity() |
| maxCapacity | 返回 ByteBuf 可以容纳的最大字节数 |
| hasArray | 如果 ByteBuf 由一个字节数组支撑,则返回 true |
| array | 如果 ByteBuf 由一个字节数组支撑则返回该数组;否则,它将抛出一个UnsupportedOperationException 异常 |
ByteBuf缓冲分类
1、Heap buffer(堆缓冲区):
就是将数据存在JVM堆空间中,在没有被池化的情况可以快速分配和释放。
优点:由于数据是存储在JVM堆中,因此可以快速的创建与快速的释放,并且它提供了直接访问内部字节数组的方法。
缺点:每次读写数据时,都需要先将数据复制到直接缓冲区中再进行网路传输。
2、Direct buffer(直接缓冲区):
直接缓冲区,在堆外直接分配内存空间,直接缓冲区并不会占用堆的容量空间,因为它是由操作系统在本地内存进行的数据分配。
优点:在使用Socket进行数据传递时,性能非常好,因为数据直接位于操作系统的本地内存中,所以不需要从JVM将数据复制到直接缓冲区中 。
缺点:因为Direct Buffer是直接在操作系统内存中的,所以内存空间的分配与释放要比堆空间更加复杂,而且速度要慢一些。
注意:
如果你的数据包含在一个在堆上的分配的缓冲区中,那么事实上,在通过套接字发送他之前,jvm将会在内部把你的缓冲区复制到一个直接缓冲区中;这样分配释放就比较浪费资源;
建议:
直接缓冲区并不支持通过字节数组的方式来访问数据。对于后端业务的消息编解码来说,推荐使用HeapByteBuf;对于I/O通信线程在读写缓冲区时,推荐使用DirectByteBuf;
3、Composite Buffer 复合缓冲区:
可以拥有以上两种的缓冲区,通过一种聚合视图来操作底层持有的多种类型Buffer。这种缓冲,jdk nio是没有这种特性的。
ByteBuf主要实现类
pooled:池化,重用ByteBuf对象
Direct:直接内存,内部通过ByteBuffer实现,典型装饰模式
Heap:堆内存,内部持有byte数组
(1)UnpooledDirectByteBuf:
在堆外进行内存分配的非内存池ByteBuf,内部持有ByteBuffer对象,相关操作委托给ByteBuffer实现。
(2)UnpooledHeapByteBuf:
基于堆内存分配非内存池ByteBuf,即内部持有byte数组。
(3)UnpooledUnsafeDirectByteBuf:
和另外一个类UnpooledDirectByteBuf差不多相同,区别在于UnpooledUnsafeDirectByteBuf内部使用基于PlatformDependent相关操作实现ByteBuf,依赖平台。
(4)ReadOnlyByteBufferBuf:
只读ByteBuf,内部持有ByteBuffer对象,相关操作委托给ByteBuffer实现,该ByteBuf限内部使用;
(5)FixedCompositeByteBuf:
用于将多个ByteBuf组合在一起,形成一个虚拟的只读ByteBuf对象,不允许写入和动态扩展。内部使用Object[]将多个ByteBuf组合在一起,一旦FixedCompositeByteBuf对象构建完成,则不会被更改。
(6)CompositeByteBuf:
用于将多个ByteBuf组合在一起,形成一个虚拟的ByteBuf对象,支持读写和动态扩展。内部使用List组合多个ByteBuf。一般使用使用ByteBufAllocator的compositeBuffer()方法,Unpooled的工厂方法compositeBuffer()或wrappedBuffer(ByteBuf... buffers)创建CompositeByteBuf对象。
(7)PooledByteBuf:
基于内存池的ByteBuf,主要为了重用ByteBuf对象,提升内存的使用效率;适用于高负载,高并发的应用中。主要有PooledDirectByteBuf,PooledHeapByteBuf,PooledUnsafeDirectByteBuf三个子类,PooledDirectByteBuf是在堆外进行内存分配的内存池ByteBuf,PooledHeapByteBuf是基于堆内存分配内存池ByteBuf,PooledUnsafeDirectByteBuf也是在堆外进行内存分配的内存池ByteBuf,区别在于PooledUnsafeDirectByteBuf内部使用基于PlatformDependent相关操作实现ByteBuf,具有平台相关性。
Netty入门(一):ByteBuf的更多相关文章
- 网络编程Netty入门:ByteBuf分析
目录 Netty中的ByteBuf优势 NIO使用的ByteBuffer有哪些缺点 ByteBuf的优势和做了哪些增强 ByteBuf操作示例 ByteBuf操作 简单的Demo示例 堆内和堆外内存 ...
- Netty入门(四)ByteBuf 字节级别的操作
Netty 中使用 ByteBuf 代替 Java NIO 提供的 ByteBuffer 作为字节的容器. 一.索引 ByteBuf 提供两个指针变量支持读和写操作,读操作使用 readerInde ...
- Netty入门之HelloWorld
Netty系列入门之HelloWorld(一) 一. 简介 Netty is a NIO client server framework which enables quick and easy de ...
- Netty入门
一.NIO Netty框架底层是对NIO的高度封装,所以想要更好的学习Netty之前,应先了解下什么是NIO - NIO是non-blocking的简称,在jdk1.4 里提供的新api,他的他的特性 ...
- netty入门(一)
1. netty入门(一) 1.1. 传统socket编程 在任何时候都可能有大量的线程处于休眠状态,只是等待输入或者输出数据就绪,这可能算是一种资源浪费. 需要为每个线程的调用栈都分配内存,其默认值 ...
- Netty入门(三)之web服务器
Netty入门(三)之web服务器 阅读前请参考 Netty入门(一)之webSocket聊天室 Netty入门(二)之PC聊天室 有了前两篇的使用基础,学习本文也很简单!只需要在前两文的基础上稍微改 ...
- Netty入门(一)之webSocket聊天室
一:简介 Netty 是一个提供 asynchronous event-driven (异步事件驱动)的网络应用框架,是一个用以快速开发高性能.高可靠性协议的服务器和客户端. 换句话说,Netty 是 ...
- Netty入门(1) - 简介
什么是Netty? Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架. Tomcat和Netty有什么区别? Netty和Tom ...
- Netty入门教程——认识Netty
什么是Netty? Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架. Netty 是一个广泛使用的 Java 网络编程框架(N ...
- Netty 系列(三)Netty 入门
Netty 系列(三)Netty 入门 Netty 是一个提供异步事件驱动的网络应用框架,用以快速开发高性能.高可靠性的网络服务器和客户端程序.更多请参考:Netty Github 和 Netty中文 ...
随机推荐
- Typescript学习总结
typescript(以下简称TS)出来也有好长时间了,下面记录一下学习心得. 首先学这门语言前,请确保有以下基础知识: 扎实的javascript基础知识 es6的基础知识 面向对象编程的概念(没有 ...
- docker部署的nginx非80端口无法访问
请检查nginx容器是否只开启了80端口映射!!! 请检查nginx容器是否只开启了80端口映射!!! 请检查nginx容器是否只开启了80端口映射!!! 如果你访问的端口在nignx容器已经开启了端 ...
- win10 共享文件夹设置无需用户名密码访问
文件夹设置共享,添加Everyone 文件夹右键属性,选择共享,添加Everyone,添加后可设置读写权限. 权限添加Everyone,不然没有权限访问 设置安全策略 Win+R 打开运行,输入 se ...
- 面试题二:JVM
JVM垃圾回收的时候如何确定垃圾? 有2种方式: 引用计数 每个对象都有一个引用计数属性,新增一个引用时计数加1,引用释放时计数减1,计数为0时可以回收: 缺点:无法解决对象循环引用的问题: 可达性分 ...
- 资源:Intellij IDEA 最新旗舰版注册激活破解*附注册码(2020年亲测)
永久激活 1. 下载jetbrains-agent.jar包(2020.03.22亲测) 链接: https://pan.baidu.com/s/1BFXPwlROEF03BkhGzGIgEA 提取码 ...
- Redis的并发竞争问题,你用哪些方案来解决?
Redis的并发竞争问题,主要是发生在并发写竞争. 考虑到redis没有像db中的sql语句,update val = val + 10 where ...,无法使用这种方式进行对数据的更新. 假如有 ...
- 第三章 深入理解python语言
计算机技术的演进过程 1946-1981年 计算机系统结构时代(35年) 解决计算机能力的问题 1981-2008年 网络和视窗时代(27年) 解决交互问题 2008-2016年 复杂信息系统时代(8 ...
- Java | Map集合
Map集合 在现实生活中,有非常多的东西,是和另外一种东西对应的,并且还是唯一的,比如:身份证号与个人,个人与手机,一夫一妻...等,这种关系就是对应关系,又叫做映射.Java为这种数据类型提供了专门 ...
- 重置networker9.0密码
一.重置Networker 9.0密码 下面所有步骤在Networker服务器上操作 1.创建"mypassword_in.txt"文件 在服务器C盘根目录下创建一个 " ...
- 5.Java流程控制
所有的流程控制语句都可以相互嵌套.互不影响 一.用户交互Scanner Scanner对象 之前我们学的基本语法中我们并没有实现程序和人的交互,但是Java给我们提供了这样一个工具类,我们可以获取用户 ...