DotNetty ByteBuffer

DotNetty是一个高性能的.NET网络通信框架,基于Netty,支持TCP、UDP、HTTP、WebSocket等协议。适用于高并发、低延迟场景,如实时通信、游戏服务器、IoT应用及大型分布式系统,通过异步I/O、零拷贝等技术提升性能,具备易用性、可扩展性。
架构上,围绕Channel、EventLoop、ChannelPipeline、ChannelHandlerContext设计,包含Transport、Codec、Handler等模块,简化网络编程,加速数据传输处理。

ByteBuffer 用于高效处理字节数据,固定容量,通过allocate或wrap创建。涉及position和limit追踪读写位置,提供get/put等读写方法,flip切换读写模式,clear清空缓冲区,compact移动数据并准备下一轮读写,适用于高性能IO与网络通信。.

优点
零拷贝通过复合缓冲区实现。
动态容量增长。
无需flip切换读写模式。
分离读写索引。
内置引用计数。
支持缓冲区池化。
优化网络通信中的字节处理。

结构
readerIndex 读取,随读增。
writerIndex 写入,随写增。
capacity容量。
在这里插入图片描述
ByteBuffer属性
readIndex:下一个读位
writeIndex:下一个写位置
capacity:容量
0:缓冲区开始位置

已经读取的区域:[0,readerindex)
可读取的区域:[readerindex,writerIndex)
可写的区域: [writerIndex,capacity)
读写独立索引,操作命名区分(read/write自动进,get/set不影响索引)。
支持设定最大容量,超限写操作将抛异常,默认上限Integer.MAX_VALUE。
readerIndex writerIndex 本质为灵活高效字节容器

堆缓冲区
最常用的 ByteBuffer 模式是将数据存储在堆空间中。这种模式被称为支撑数组(backing array),它能在没有使用池化的情况下提供快速的分配和释放。可以由 hasArray() 来判断检查 ByteBuffer是否由数组支撑。如果不是,则这是一个直接缓冲区。

直接缓冲区
直接缓冲区是另外一种 ByteBuffer 模式。
直接缓冲区的主要缺点是,相对于基于堆的缓冲区,它们的分配和释放都较为昂贵。

复合缓冲区
复合缓冲区 CompositeByteBuf,它为多个 ByteBuffer提供一个聚合视图。比如 HTTP 协议, 分为消息头和消息体,这两部分可能由应用程序的不同模块产生,各有各的 ByteBuffer,将会在消息被发送的时候组装为一个 ByteBuffer,此时可以将这两个 ByteBuffer聚合为一个 CompositeByteBuf,然后使用统一和通用的 ByteBuffer API 来操作。

如何在的程序中获得 ByteBuf 的实例,并使用它呢?Netty 提供了两种方式

ByteBufAllocator 接口
ByteBufAllocator 分配任意类型的 ByteBuffer 实例。

buffer(): 基于堆/直接内存ByteBuffer。
heapBuffer(): 仅堆内存。
directBuffer(): 仅直接内存。
compositeBuffer(): 可组合多个缓冲区,支持堆/直接内存。
ioBuffer(): 适配I/O操作,优先直接内存(需Unsafe支持)。
ByteBufAllocator:
Channel ChannelHandlerContext

Unpooled 缓冲区

Unpooled工具类助创ByteBuffer
buffer():堆内存ByteBuffer
directBuffer():直接内存ByteBuffer
wrappedBuffer():包装数据的ByteBuffer
copiedBuffer():复制数据的ByteBuffer 适用范围广泛,不仅限于Netty网络项目。

 IByteBuffer byteBuf = Unpooled.CopiedBuffer("hello,world!", Encoding.UTF8); 

ByteBuf访问/读写
索引从0开始至capacity()-1。
随机访问(get/set)不改索引,需显式调用readerIndex()/writerIndex()移动。
顺序访问分两类:
get/set:固定索引,读写数据不移位。
read/write:自动调整readerIndex/writerIndex。

isReadable() 如果至少有一个字节可供读取,则返回 true
isWritable() 如果至少有一个字节可被写入,则返回 true
readableBytes() 返回可被读取的字节数
writableBytes() 返回可被写入的字节数
capacity() 返回 ByteBuffer 可容纳的字节数。在此之后,它会尝试再次扩展直到达到
maxCapacity()
maxCapacity() 返回 ByteBuffer 可以容纳的最大字节数
hasArray() 如果 ByteBuffer 由一个字节数组支撑,则返回 true
array() 如果 ByteBuffer 由一个字节数组支撑则返回该数组

可丢弃字节
读操作后,字节积累在"可丢弃"段,始于readerIndex。
discardReadBytes()释放已读字节,回收空间,可能导致之前数据移动。
此操作可能涉及内存复制,谨慎使用。

在这里插入图片描述

可读字节:存储实际数据,新缓冲区默认从readerIndex=0开始。
可写字节:空白区域待写入,新缓冲区writerIndex初设0,写操作后自动递增。
在这里插入图片描述

资源释放
处理Netty入站ByteBuffer ,可选自动释放:用SimpleChannelInboundHandler,或在channelRead()末手动调用ReferenceCountUtil.release(msg)确保资源管理。

using DotNetty.Buffers;
using DotNetty.Transport.Channels;

public class CommanChannelInboundHandler : SimpleChannelInboundHandler<object>
{
    protected override void ChannelRead(IChannelHandlerContext context, object message)
    {
        bool shouldRelease = true;

        try
        {
            if (IsMessageAcceptable(message))
            {
                ChannelRead0(context, message);
            }
            else
            {
                shouldRelease = false;
                context.FireChannelRead(message);
            }
        }
        finally
        {
            if (AutoRelease && shouldRelease)
            {
                ResourceUtil.Release(message);
            }
        }
    }

    private bool IsMessageAcceptable(object msg)
    {
       
        return msg is IByteBuffer; // 假设只处理IByteBuffer类型的消息
    }

    protected virtual void ChannelRead0(IChannelHandlerContext context, object message)
    {
        //IByteBuffer ...
    }

   
    private bool AutoRelease { get; set; } = true;
}

对于出站请求,不管 ByteBuffer 是否由我们的业务创建的,当调用了 write 或者 writeAndFlush 方法后,Netty 会自动替我们释放,不需要我们业务代码自行释放。

   // 创建ByteBuf对象,初始容量为1,内部动态扩容以容纳更多数据
   IByteBuffer byteBuf = Unpooled.Buffer(1);
   Console.WriteLine("byteBuf=" + byteBuf);

   for (int i = 0; i < 8; i++)
   {
       byteBuf.WriteByte(i);
   }
   Console.WriteLine("byteBuf=" + byteBuf);

   for (int i = 0; i < 5; i++)
   {
       Console.WriteLine(byteBuf.GetByte(i));
   }
   Console.WriteLine("byteBuf=" + byteBuf);

   for (int i = 0; i < 5; i++)
   {
       Console.WriteLine(byteBuf.ReadByte());
   }
   Console.WriteLine("byteBuf=" + byteBuf);

   //byteBuf2
   // 使用Unpooled工具类创建ByteBuf,内容为"hello,world!"
   IByteBuffer byteBuf2 = Unpooled.CopiedBuffer("hello,world!", Encoding.UTF8); // Unpooled.CopiedBuffer("hello,world!", Encoding.UTF8);
   // 使用相关的方法
   if (byteBuf2.HasArray) // if (byteBuf2.HasArray)
   {
       byte[] content = byteBuf2.Array;
       // 将content转成字符串
       Console.WriteLine(Encoding.UTF8.GetString(content));
       Console.WriteLine("byteBuf2=" + byteBuf2);

       Console.WriteLine(byteBuf2.GetByte(0)); // 获取数组0这个位置的字符'h'的ASCII码,h=104

       int len = byteBuf2.ReadableBytes; // 可读的字节数 12
       Console.WriteLine("len=" + len);

       // 使用for取出各个字节并转换为对应的字符打印
       for (int i = 0; i < len; i++)
       {
           Console.WriteLine((char)byteBuf2.GetByte(i));
       }

       // 范围读取
       Console.WriteLine(byteBuf2.GetCharSequence(0, 6, Encoding.UTF8));
       Console.WriteLine(byteBuf2.GetCharSequence(6, 6, Encoding.UTF8));
   }


   //byteBuf3 WrappedBuffer
   var str1 = Encoding.UTF8.GetBytes("hello,world!");
   var byteBuf3 = Unpooled.WrappedBuffer(str1);
   if (byteBuf3.HasArray) // if (byteBuf2.HasArray)
   {
       byte[] content = byteBuf3.Array;
       // 将content转成字符串
       Console.WriteLine(Encoding.UTF8.GetString(content));
       Console.WriteLine("byteBuf3=" + byteBuf3);

       Console.WriteLine(byteBuf3.GetByte(0)); // 获取数组0这个位置的字符'h'的ASCII码,h=104

       int len = byteBuf3.ReadableBytes; // 可读的字节数 12
       Console.WriteLine("len=" + len);

       // 使用for取出各个字节并转换为对应的字符打印
       for (int i = 0; i < len; i++)
       {
           Console.WriteLine((char)byteBuf3.GetByte(i));
       }

       // 范围读取
       Console.WriteLine(byteBuf3.GetCharSequence(0, 6, Encoding.UTF8));
       Console.WriteLine(byteBuf3.GetCharSequence(6, 6, Encoding.UTF8));
   }

结果得出 get操作 readerIndex 不变,read操作使其移动。

End

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/639152.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ubuntu使用记录——如何使用wireshark网络抓包工具进行检测速腾激光雷达的ip和端口号

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言wireshark网络抓包工具1.wireshark的安装2.wireshark的使用3.更改雷达ip 总结 前言 Wireshark是一款备受赞誉的开源网络协议分析软件&#xff0c;其功能之强大…

案例题(第二版)

案例题目 信息系统架构设计 基本概念 信息系统架构&#xff08;ISA&#xff09;是对某一特定内容里的信息进行统筹、规划、设计、安排等一系列的有机处理的活动。特点如下 架构是对系统的抽象&#xff0c;它通过描述元素、元素的外部可见属性及元素之间的关系来反映这种抽象…

YashanDB与慧点科技完成兼容互认证

近日&#xff0c;深圳计算科学研究院崖山数据库系统YashanDB与慧点科技顺利完成兼容性互认证。经严格测试&#xff0c;双方产品完全兼容&#xff0c;稳定运行&#xff0c;共同支撑政府、企业、金融等办公应用场景下的数字化转型升级&#xff0c;为企业的信息技术应用创新提供坚…

【全部更新完毕】2024长三角数学建模A题思路代码文章教学-“抢救”落水手机

文章摘要部分&#xff1a; “抢救”落水手机 摘要 文章主要探讨了如何科学地处理和搜索在水体中意外掉落的物品&#xff1a;华为 Mate 60 Pro手机和居民身份证。本文基于物理模型和动力学分析&#xff0c;为不同水体环境中的掉落物品提供了详尽的搜索策略和打捞建议。 本文…

华为手机卡顿(仅针对于部分人来说,我也不清楚是否真的有用)

关机&#xff01; 之前一段时间手机变得特别卡顿&#xff0c;然后网上搜了一堆教程一点用没有&#xff0c;结果因为昨天下午在考试所以把手机关机了一个多小时&#xff0c;再打开之后手机就变得很流畅&#xff0c;原因不详&#xff0c;但效果显著&#xff0c;如有需要可尝试一…

【从C++到Java一周速成】章节14:网络编程

章节14&#xff1a;网络编程 【1】网络编程的概念【2】IP地址与端口的概念【3】网络通信协议引入网络通信协议的分层 【3】Socket套接字【4】单向通信【5】双向通信 【1】网络编程的概念 把分布在不同地理区域的计算机与专门的外部设备用通信线路互联成一个规模大、功能强的网…

SpringCloud Alibaba详解:打造高可用的分布式系统

SpringCloud Alibaba是一个基于Spring Cloud的微服务开发框架&#xff0c;它集成了阿里巴巴的一系列中间件和工具&#xff0c;能够快速构建高可用的分布式系统。在本文中&#xff0c;将详细介绍如何使用SpringCloud Alibaba来打造高可用的分布式系统&#xff0c;并通过代码案例…

jenkins插件之Warnings

Warnings插件&#xff0c;收集静态分析工具报告的编译器警告或问题&#xff0c;并将结果可视化。它内置了对许多编译器的支持&#xff08;cpp&#xff0c;clang&#xff0c;java等&#xff09;和工具&#xff08;spotbugs&#xff0c;pmd&#xff0c;checkstyle&#xff0c;esl…

本是梦中人,常作花下客。心中自往来,知我有几个。

我们总是喜欢拿“顺其自然”来敷衍人生道路上的荆棘坎坷&#xff0c;却很少承认&#xff0c;真正的顺其自然&#xff0c; 其实是竭尽所能之后的不强求&#xff0c; 而非两手一摊的不作为。 一花凋零荒芜不了整个春天&#xff0c; 一次挫折也荒废不了整个人生。 多年后&#x…

HQL面试题练习 —— 品牌营销活动天数

题目来源&#xff1a;小红书 目录 1 题目2 建表语句3 题解 1 题目 有营销活动记录表&#xff0c;记录了每个品牌每次营销活动的开始日期和营销活动的结束日期&#xff0c;现需要统计出每个品牌的总营销天数。 注意&#xff1a; 1:苹果第一行数据的营销结束日期比第二行数据的营…

Mask R-CNN实战

一、源码和数据集的准备 获取git开源项目代码 https://github.com/matterport/Mask_RCNN 一下载2.1的前三个文件&#xff0c;和2.0的第一个h5文件&#xff0c;coco.h5是预训练权重&#xff0c;也放入源码 项目文件结构如下&#xff1a; samples/logs:训练模型保存的位置 配置…

GeoScene产品学习视频收集

1、易智瑞运营的极思课堂https://www.geosceneonline.cn/learn/library 2、历年易智瑞技术公开课视频资料 链接&#xff1a;技术公开课-易智瑞信息技术有限公司&#xff0c;GIS/地理信息系统&#xff0c;空间分析-制图-位置智能-地图 3、一些关于GeoScene系列产品和技术操作的视…

【FixBug】超级大Json转POJO失败

今天遇到了一个问题&#xff1a;使用Jackson将一个超级大的JSON字符串转换POJO失败&#xff0c;debug看没问题&#xff0c;将JSON字符串粘贴到main方法中测试&#xff0c;提示错误信息如下&#xff1a; 自己猜测是因为字符串超长导致转换时先截断字符串导致JSON格式不正确&…

20232802 黄千里 2023-2024-2 《网络攻防实践》实践十一报告

20232802 2023-2024-2 《网络攻防实践》实践十一报告 1.实践过程 1.1web浏览器渗透攻击 攻击机&#xff1a;kali172.20.10.10靶机&#xff1a;win2k172.20.10.3 首先在kali中启动msfconsole 输入命令search MS06-014&#xff0c;搜索渗透攻击模块 输入use exploit/window…

基于jeecgboot-vue3的Flowable增加流程支持组件与element-plus组件导入支持

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、package.json文件需要增加相关流程组件&#xff0c;如下 "dependencies": {"element-plus/icons-vue": "^2.3.1","highlightjs/vue-plugin":…

设备管理全解析:从选购到报废的全方位指南

在现代企业快速发展、智能化运营过程中&#xff0c;企业设备管理是保障生产连续性和效率的核心环节&#xff0c;其重要性不言而喻。然而&#xff0c;许多企业在设备管理内容流程方面仍然使用传统管理办法&#xff0c;这不仅影响了生产效率&#xff0c;也增加了不必要的成本。那…

二叉树创建与销毁操作详解

目录 一、通过前序遍历的数组构建二叉树 1.1 递归思路 1.2 递归分支图 1.3 递归栈帧图 1.4 C语言实现 二、二叉树的销毁 2.1 递归思路 2.2 递归分支图 2.3 递归栈帧图 2.4 C语言实现 一、通过前序遍历的数组构建二叉树 牛客网链接&#xff1a;二叉树遍历_牛客题霸_牛…

Spring ----> IOC

文章目录 一、 Spring 是一个包含众多工具的IoC容器二、 什么是IOC以及好处三、 如何实现loc思想四、Spring提供的实现loC的方法 --- 类注解方法注解4.1 类注解类注解概念介绍类注解的使用 4.2 方法注解Bean 一、 Spring 是一个包含众多工具的IoC容器 场景解析&#xff1a;首先…

分布式事务解决方案(强一致性)

强一致性事务概述 分布式事务领域&#xff0c;最早采用的是符合CAP理论的强一致性事务方案来解决分布式事务问题&#xff0c;强一致性分布式事务要求在任意时刻查询参与全局事务的各个节点的数据都是一致的 典型案例&#xff1a; 包括DTP模型&#xff08;全局事务模型&#x…

微软Power Automate平台将引入AI工作流

最近的微软 Build 大会展示了许多新的计划和增强功能&#xff0c;特别是围绕将 AI 集成到微软的产品和平台中。一个重点是扩展 Microsoft Copilot 在各种应用和服务中的功能。此外&#xff0c;微软还宣布对 Azure AI 进行了重大更新&#xff0c;旨在使云计算更加有用。虽然在 B…