【Netty】 ByteBuf的常用API总结
目录
一、ByteBuf介绍
二、ByteBuf创建
1.池化创建 ByteBufAllocator
2.Unpooled (非池化)创建ByteBuf
3.ByteBufUtil 操作ByteBuf
三、读取ByteBuf数据
1.get方法
2.read方法
3.set方法
4.write方法
5.索引管理
6.索引查找
7.索引查找
8.其他方法
本篇主要介绍ByteBuf的常用操作API,Netty性能的卓越表现离不开ByteBuf的巧妙设计,它提供了一系列的缓冲区读写方法,另外为了方便起见还特定义了ByteBufUtil,提供了比较丰富的操作ByteBuf方法。
一、ByteBuf介绍
为了提高性能,Netty重新设计了字节缓冲区ByteBuf,类似Java Nio的ByteBuffer,但工作方式略有区别,比后者更加灵活、高效。
ByteBuf有几个重要属性:
capacity:容量;
0:缓冲区开始位置;
readIndex:下一个读位置;
writeIndex:下一个写位置;
一个ByteBuf对象即可像byte数组一样工作,又可以像IO字节流一样工作。当前的可读数据区是[readIndex,writeIndex);可写区是[writeIndex,capacity);而[0,readIndex)区间的字节是可废弃数据(Discardable),如下图所示:
+-------------------+------------------+------------------+
| discardable bytes | readable bytes | writable bytes |
| | (CONTENT) | |
+-------------------+------------------+------------------+
| | | |
0 <= readerIndex <= writerIndex <= capacity
基本的操作包括
1.从ByteBuf中读取数据,从readerIndex开始向后读取需要的字节数,readerIndex随之改变;
2.向ByteBuf中写数据,从writeIndex开始向后写数据,同时writeIndex随之改变;
3.删除ByteBuf已读数据,从[0,readerIndex)为已读完的数据,为了节省空间需要释放内存,释放示意图如下:
* BEFORE discardReadBytes()** +-------------------+------------------+------------------+* | discardable bytes | readable bytes | writable bytes |* +-------------------+------------------+------------------+* | | | |* 0 <= readerIndex <= writerIndex <= capacity*** AFTER discardReadBytes()** +------------------+--------------------------------------+* | readable bytes | writable bytes (got more space) |* +------------------+--------------------------------------+* | | |* readerIndex (0) <= writerIndex (decreased) <= capacity
4.清空ByteBuf数据,不需要清空数据,通过移动两个指针readerIndex和writeIndex,指向0即可。
* BEFORE clear()** +-------------------+------------------+------------------+* | discardable bytes | readable bytes | writable bytes |* +-------------------+------------------+------------------+* | | | |* 0 <= readerIndex <= writerIndex <= capacity*** AFTER clear()** +---------------------------------------------------------+* | writable bytes (got more space) |* +---------------------------------------------------------+* | |* 0 = readerIndex = writerIndex <= capacity
二、ByteBuf创建
1.池化创建 ByteBufAllocator
即PooledByteBufAllocator
获取ByteBufAllocator,通过以下两种方式获取
//方法1
Channel channel = ...;
ByteBufAllocator allocator = channel.alloc();
//方法2
ChannelHandlerContext ctx = ...;
ByteBufAllocator allocator2 = ctx.alloc();
ByteBufAllocator中创建byteBuf的方法如下
| 方法名称 | 方法描述 |
| buffer() buffer(int) buffer(int, int) | Return a ByteBuf with heap-based or direct data storage |
| heapBuffer() heapBuffer(int) heapBuffer(int, int) | Return a ByteBuf with heap-based storage. |
| directBuffer() directBuffer(int) directBuffer(int, int) | Return a ByteBuf with direct storage. |
| compositeBuffer() compositeBuffer(int) heapCompositeBuffer() heapCompositeBuffer(int) directCompositeBuffer() directCompositeBuffer(int) | Return a CompositeByteBuf that can be expanded by adding heapbased or direct buffers. |
| ioBuffer() | Return a ByteBuf that will be used for I/O operations on a socket. |
2.Unpooled (非池化)创建ByteBuf
即UnPooledByteBufAllocator
当未引用 ByteBufAllocator 时,上面的方法无法访问到 ByteBuf。对于这个用例 Netty 提供一个实用工具类称为 Unpooled,,它提供了静态辅助方法来创建非池化的 ByteBuf 实例,方法如下:
| 方法名称 | 方法描述 |
| buffer() buffer(int) buffer(int, int) | Returns an unpooled ByteBuf with heap-based storage |
| directBuffer() directBuffer(int) directBuffer(int, int) | Returns an unpooled ByteBuf with direct storage |
| wrappedBuffer() | Returns a ByteBuf, which wraps the given data. |
| copiedBuffer() | Returns a ByteBuf, which copies the given data |
3.ByteBufUtil 操作ByteBuf
三、读取ByteBuf数据
get/read get不会改变读索引,read会改变读索引
1.get方法
| 方法名称 | 方法描述 |
| getBoolean(int) | 返回当前索引的 Boolean 值 |
| getByte(int) getUnsignedByte(int) | 返回当前索引的(无符号)字节 |
| getMedium(int) getUnsignedMedium(int) | 返回当前索引的 (无符号) 24-bit 中间值 |
| getInt(int) getUnsignedInt(int) | 返回当前索引的(无符号) 整型 |
| getLong(int) getUnsignedLong(int) | 返回当前索引的 (无符号) Long 型 |
| getShort(int) getUnsignedShort(int) | 返回当前索引的 (无符号) Short 型 |
| getBytes(int, ...) | 字节 |
2.read方法
| 方法名称 | 方法描述 |
| readBoolean() | 返回当前索引的Boolean值,读索引加一 |
| readByte() readUnsignedByte() | 返回当前索引的(无符号)字节,读索引加一 |
| readMedium() readUnsignedMedium() | 返回当前索引的 (无符号) 24-bit 中间值,读索引加3 |
| readInt() readUnsignedInt() | 返回当前索引的(无符号) 整型,读索引加4 |
| readLong() readUnsignedLong() | 返回当前索引的 (无符号) Long 型,读索引加8 |
| readShort() readUnsignedShort() | 返回当前索引的 (无符号) Short 型,读索引加2 |
| readBytes(int,int, ...) | 返回当前位置到length得到一个字节数组,读索引加length |
3.set方法
| 方法名称 | 方法描述 |
| setBoolean(int, boolean) | 在指定的索引位置设置 Boolean 值 |
| setByte(int, int) | 在指定的索引位置设置 byte 值 |
| setMedium(int, int) | 在指定的索引位置设置 24-bit 中间 值 |
| setInt(int, int) | 在指定的索引位置设置 int 值 |
| setLong(int, long) | 在指定的索引位置设置 long 值 |
| setShort(int, int) | 在指定的索引位置设置 short 值 |
4.write方法
| 方法名称 | 方法描述 |
| writeBoolean(boolean) | 在指定的索引位置设置 Boolean 值,写索引加一 |
| writeByte(int) | 在指定的索引位置设置 byte 值,写索引加一 |
| writeMedium(int) | 在指定的索引位置设置 24-bit 中间 值,写索引加3 |
| writeInt(int) | 在指定的索引位置设置 int 值,写索引加4 |
| writeLong(long) | 在指定的索引位置设置 long 值,写索引加8 |
| writeShort(int) | 在指定的索引位置设置 short 值,写索引加2 |
| writeBytes(int,...) | 在当前索引写入一个Byte数组,写索引加数组长度 |
5.索引管理
| 方法名称 | 方法描述 |
| markReaderIndex(), markWriterIndex() | 标记读(写)索引 |
| resetReaderIndex() resetWriterIndex() | 读(写)索引回到mark标记的索引值 |
| readerIndex(int) writerIndex(int) | 将读(写)索引设置到指定位置 |
| clear() | 可以同时设置 readerIndex 和 writerIndex 为 0。这不会清除内存中的内容 |
6.索引查找
| 方法名称 | 方法描述 |
| for EachByte(ByteBufProcessor.FIND_NUL) | 查找byte,返回byte的索引 |
7.索引查找
| 方法名称 | 方法描述 |
| duplicate() slice(int, int) | 所有这些都返回一个新的 ByteBuf 实例包括它自己的 reader, writer 和标记索引。然而,内部数据存储共享就像在一个 NIO 的 ByteBuffer |
| copy() copy(int, int) | 返回的 ByteBuf 有数据的独立副本 |
8.其他方法
| 方法名称 | 方法描述 |
| isReadable() | 返回是否有字节可读 |
| isWritable() | 返回是否可以写 |
| readableBytes() | 返回可以读的字节长度 |
| writablesBytes() | 返回可以写的字节长度 |
| capacity() | 返回byteBuf的容量 |
| maxCapacity() | 返回byteBuf可以有的最大容量 |
| hasArray() | 如果byteBuf可以直接返回一个数组就返回true (heap buf才会为true) |
| array() | hasArray返回true,该方法就会返回一个数组 |
参考资料
ByteBuf的常用API总结
Netty详解之九:ByteBuf介绍
相关文章:
【Netty】 ByteBuf的常用API总结
目录 一、ByteBuf介绍 二、ByteBuf创建 1.池化创建 ByteBufAllocator 2.Unpooled (非池化)创建ByteBuf 3.ByteBufUtil 操作ByteBuf 三、读取ByteBuf数据 1.get方法 2.read方法 3.set方法 4.write方法 5.索引管理 6.索引查找 7.索引查找 8.其…...
热门敏捷开发管理工具
敏捷管理研发工具可以协助团队更好地进行敏捷开发和管理。以下是几种流行的敏捷管理研发工具: Leangoo:Leangoo领歌一款永久免费的专业敏捷研发管理工具,它覆盖了敏捷项目研发全流程,包括小型团队敏捷开发,规模化敏捷…...
Java分支结构:一次不经意的选择,改变了我的一生。
👑专栏内容:Java⛪个人主页:子夜的星的主页💕座右铭:前路未远,步履不停 目录 一、顺序结构二、分支结构1、if语句2、switch语句 好久不见!命运之轮常常在不经意间转动,有时一个看似微…...
Unity中Shader需要了解的点与向量
文章目录 前言一、点和向量的区别二、向量加法减法1、向量加法2、向量减法(可以把向量减法转化为向量加法) 三、向量的模四、标量1、向量与标量的乘法 前言 Unity中Shader了解使用的…...
Java初始化大量数据到Neo4j中(一)
背景:我们项目第一次部署图数据库,要求我们把现有的业务数据以及关系上线第一时间初始化到Neo4j中。开发环境数据量已经百万级别。生成环境数据量更多。 我刚开始开发的时候,由于对Neo4j的了解并没有很多,第一想到的是用代码通用组…...
Excel·VBA日期时间转换提取正则表达式函数
标准日期转换 Function 标准日期(ByVal str$) As DateDim pat$, result$arr Array("(\d{4}).*?(\d{1,2}).*?(\d{1,2})", "(\d{4}).*?(\d{1}).*?(\d{1,2})")If Len(str) < 8 Then pat arr(1) Else pat arr(0)With CreateObject("vbscript.r…...
Django中的缓存
Django中的缓存 缓存的定义 定义: 缓存是-类可以更快的读取数据的介质统称,也指其它可以加快数据读取的存储方式。一般用来存储临时数据,常用介质的是读取速度很快的内存 意义:视图渲染有一定成本,数据库的频繁查询过高;所以对于低频变动的页…...
Python 编程基础 | 第二章-基础语法 | 2.4、while 语句
一、while 语句 1、循环语句 Python 编程中 while 语句用于循环执行程序,其基本形式为: while 判断条件(condition):执行语句(statements)……例如: count 0 while (count < 9):print(count)count 1while 语句时还有另外两个…...
Qt Charts简介
文章目录 一.图标类型Charts分类1.折线图和样条曲线图2.面积图和散点图3.条形图4.饼图5.误差棒图6.烛台图7.极坐标图 二.坐标轴Axes类型分类三.图例四.图表的互动五.图表样式主题 一.图标类型Charts分类 图表是通过使用系列类的实例并将其添加到QChart或ChartView实例来创建的…...
MinGW、GCC、GNU和MSVC是什么?有什么区别?
在C和C开发中,常常会遇到MinGW、GCC、GNU和MSVC这些术语。本教程将向您解释它们的含义以及它们之间的区别,帮助您更好地理解这些常见的编译工具和开发环境。 MinGW(Minimalist GNU for Windows): MinGW是一个开源的软件…...
引入easyExcel后,导致springboot项目无法开启tomcat
报错信息: Caused by: java.lang.annotation.IncompleteAnnotationException: org.terracotta.statistics.Statistic missing element type at sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:81) at com.sun.proxy…...
Doris数据库FE——启动流程源码详细解析
Doris中FE主要负责接收和返回客户端请求、元数据以及集群管理、查询计划生成等工作。代码路径:doris/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java 环境检查 在启动FE的时候,主要做环境检查。检查一些启动时必要的环境变量以及初始化配置…...
服务断路器_Resilience4j线程池隔离实现
线程池隔离配置修改YML文件 resilience4j:thread-pool-bulkhead: instances:backendA:# 最大线程池大小maxThreadPoolSize: 4# 核心线程池大小coreThreadPoolSize: 2# 队列容量queueCapacity: 2编写controller /*** 测试线程池服务隔离* return*/Bulkhead(name "backe…...
原神启动原神启动原神启动原神启动
测试游戏抽卡场景是确保玩家可以正常抽取虚拟物品或角色的重要部分。以下是一些可能的游戏抽卡场景的测试用例示例: 1.正常抽卡流程: 2.测试用户是否能够成功进行一次或多次抽卡操作。 3.确保每次抽卡后,用户收到相应的物品或角色。 4.抽卡…...
Glide - Android的图像加载和缓存库,专注于平滑滚动
官网 GitHub - bumptech/glide: An image loading and caching library for Android focused on smooth scrolling 项目介绍 An image loading and caching library for Android focused on smooth scrolling Glide is a fast and efficient open source media management a…...
如何使用 API 接口获取商品数据,从申请 API 接口、使用 API 接口到实际应用,一一讲解
在当今的数字化时代,应用程序接口(API)已经成为数据获取的重要通道。API 接口使得不同的应用程序能够方便地进行数据交换,从而促进了信息的广泛传播和利用。在众多的数据源中,商品数据是一个非常重要的领域,…...
苹果 CMS 原生 Java 白菜影视 App 源码【带打包教程】
苹果 CMS 原生 Java 白菜影视 App 源码是一款功能强大的影视应用程序,支持画中画、投屏、点播、播放前广告和支持普通解析等多种功能。与萝卜 App 源码相比,该套源码更加稳定,且拥有画中画投屏和自定义广告等功能,提高了安全性。 …...
Flutter开发之Package与Plugin
前言 在flutter中有包和插件两个概念,插件 (plugin) 是 package 的一种,全称是 plugin package,我们简称为 plugin,中文叫插件。包(Package)主要指对flutter相关功能的封装,类似于Android中的插件和iOS中的三方库。而插…...
[极客大挑战 2019]RCE ME 取反绕过正则匹配 绕过disable_function设置
目录 取反 1.蚁剑插件绕过 2.baypass disable_function open_dir/disable_function putenv()/LD_PRELOAD 来绕过限制 利用条件 利用思路 有意思。。。。 <?php error_reporting(0); if(isset($_GET[code])){$code$_GET[code];if(strlen($code)>40){die("Th…...
硬盘接口随机
关于硬盘接口 1 首先,关于[物理接口、协议、通道]2 物理接口:通讯中的电,光口,“物理规格,像是公路、铁路”。通道:通讯协议中的应用层以下所有层?“县道,省道,高速&am…...
rknn优化教程(二)
文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK,开始写第二篇的内容了。这篇博客主要能写一下: 如何给一些三方库按照xmake方式进行封装,供调用如何按…...
基于ASP.NET+ SQL Server实现(Web)医院信息管理系统
医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上,开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识,在 vs 2017 平台上,进行 ASP.NET 应用程序和简易网站的开发;初步熟悉开发一…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
