Netty-读写原理

归档

  • GitHub: Netty-读写原理

读原理

  • 参考:选择器-监听-原理 sign_o_002

  • 主要看 NioByteUnsafe#read()

    • 相当于读取底层信道中的字节
  • io.netty.channel.nio.AbstractNioByteChannel.NioByteUnsafe

    • 下游链处理参考:处理器链-读流程
    protected class NioByteUnsafe extends AbstractNioUnsafe {@Overridepublic final void read() {... // 校验处理final ChannelPipeline pipeline = pipeline();/*** allocator   用于创建 ByteBuf 实例*             测试时为 io.netty.buffer.PooledByteBufAllocator 实例* allocHandle 用于计算 ByteBuf 大小(初始时的)*             测试时为 io.netty.channel.AdaptiveRecvByteBufAllocator.HandleImpl 实例*/final ByteBufAllocator allocator = config.getAllocator();final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle(); // sign_m_001 allocHandle.reset(config); // 如果是缓存的 allocHandle 则重置下ByteBuf byteBuf = null;boolean close = false;try {do {byteBuf = allocHandle.allocate(allocator);          // 分配 ByteBufallocHandle.lastBytesRead(doReadBytes(byteBuf));    // sign_m_010 读取信道内容if (allocHandle.lastBytesRead() <= 0) {... // 无数据可读,设置 close 为 true 等处理break;}allocHandle.incMessagesRead(1);pipeline.fireChannelRead(byteBuf);      // sign_o_010 发送读取的字节byteBuf = null;} while (allocHandle.continueReading());allocHandle.readComplete();pipeline.fireChannelReadComplete();         // sign_o_020 发送读取完成事件if (close) {closeOnRead(pipeline); // 关闭读}} ... // catch finally }}
  • io.netty.channel.AbstractChannel.AbstractUnsafe
    protected abstract class AbstractUnsafe implements Unsafe {private RecvByteBufAllocator.Handle recvHandle;// sign_m_001@Overridepublic RecvByteBufAllocator.Handle recvBufAllocHandle() {if (recvHandle == null) {recvHandle = config().getRecvByteBufAllocator().newHandle();}return recvHandle; // 相当于缓存}}
  • io.netty.channel.socket.nio.NioSocketChannel
public class NioSocketChannel extends AbstractNioByteChannel implements io.netty.channel.socket.SocketChannel {// sign_m_010 读取信道内容@Overrideprotected int doReadBytes(ByteBuf byteBuf) throws Exception {final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();allocHandle.attemptedBytesRead(byteBuf.writableBytes());/*** byteBuf 为 io.netty.buffer.PooledUnsafeDirectByteBuf 实例* sign_m_020 读取 Java 底层信道内容*/return byteBuf.writeBytes(javaChannel(), allocHandle.attemptedBytesRead());}
}
  • io.netty.buffer.AbstractByteBuf
public abstract class AbstractByteBuf extends ByteBuf {// sign_m_020 读取底层信道内容@Overridepublic int writeBytes(ScatteringByteChannel in, int length) throws IOException {ensureWritable(length);int writtenBytes = setBytes(writerIndex, in, length); // sign_m_030 写入内容if (writtenBytes > 0) {writerIndex += writtenBytes; // 改写索引}return writtenBytes;}
}
  • io.netty.buffer.PooledByteBuf
abstract class PooledByteBuf<T> extends AbstractReferenceCountedByteBuf {// sign_m_030 写入内容@Overridepublic final int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {try {/*** internalNioBuffer(index, length) 返回 ByteBuffer 实例* 读取信道内容到 ByteBuffer 缓冲区*/return in.read(internalNioBuffer(index, length));} catch (ClosedChannelException ignored) {return -1;}}// 返回 ByteBuffer 实例@Overridepublic final ByteBuffer internalNioBuffer(int index, int length) {checkIndex(index, length);return _internalNioBuffer(index, length, false);}// 返回 ByteBuffer 实例final ByteBuffer _internalNioBuffer(int index, int length, boolean duplicate) {index = idx(index);ByteBuffer buffer = duplicate ? newInternalNioBuffer(memory) : internalNioBuffer();buffer.limit(index + length).position(index);return buffer;}// 返回内部 ByteBuffer 实例protected final ByteBuffer internalNioBuffer() {ByteBuffer tmpNioBuf = this.tmpNioBuf;if (tmpNioBuf == null) { // 内部 ByteBuffer 实例为空,则创建this.tmpNioBuf = tmpNioBuf = newInternalNioBuffer(memory); // sign_m_040 创建 ByteBuffer 实例} else {tmpNioBuf.clear();}return tmpNioBuf;}
}
  • io.netty.buffer.PooledUnsafeDirectByteBuf
final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {// sign_m_040 创建 ByteBuffer 实例@Overrideprotected ByteBuffer newInternalNioBuffer(ByteBuffer memory) {/*** memory 为 java.nio.DirectByteBuffer 实例*/return memory.duplicate(); // 创建副本}
}

写原理

  • 主要有两部分:
    • HeadContext#write() 写入消息到缓冲区
    • HeadContext#flush() 推送消息到对端

写入

  • 调用参考:简单示例-客户端 sign_u_001

    • 调用点:channel.write(msg); // sign_u_001 写入消息
  • 上游链处理参考:处理器链-写流程

  • io.netty.channel.DefaultChannelPipeline.HeadContext

    • 最终到头节点写入
    final class HeadContext extends AbstractChannelHandlerContextimplements ChannelOutboundHandler, ChannelInboundHandler {// sign_o_030 写入消息@Overridepublic void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {/*** msg 为 io.netty.buffer.PooledUnsafeDirectByteBuf 实例* unsafe 为 io.netty.channel.socket.nio.NioSocketChannel.NioSocketChannelUnsafe 实例* sign_m_100 写入消息到信道*/unsafe.write(msg, promise);}}
  • io.netty.channel.AbstractChannel.AbstractUnsafe
    protected abstract class AbstractUnsafe implements Unsafe {// sign_m_100 写入消息到信道@Overridepublic final void write(Object msg, ChannelPromise promise) {... // 省略校验int size;try {msg = filterOutboundMessage(msg); // sign_m_110 封装处理size = pipeline.estimatorHandle().size(msg);if (size < 0) {size = 0;}} ... // catchoutboundBuffer.addMessage(msg, size, promise); // 添加要发送的缓冲区}}
  • io.netty.channel.nio.AbstractNioByteChannel
public abstract class AbstractNioByteChannel extends AbstractNioChannel {// sign_m_110 封装处理@Overrideprotected final Object filterOutboundMessage(Object msg) {if (msg instanceof ByteBuf) {ByteBuf buf = (ByteBuf) msg;if (buf.isDirect()) {return msg; // msg 为 PooledUnsafeDirectByteBuf 实例,直接返回}return newDirectBuffer(buf);}... // 省略其他处理}
}

推送

  • 参考:简单示例-客户端 sign_u_002

    • 调用点:channel.flush(); // sign_u_002 推送消息
  • io.netty.channel.DefaultChannelPipeline.HeadContext

    • 最终是头节点推送
    final class HeadContext extends AbstractChannelHandlerContextimplements ChannelOutboundHandler, ChannelInboundHandler {@Overridepublic void flush(ChannelHandlerContext ctx) {/*** unsafe 为 io.netty.channel.socket.nio.NioSocketChannel.NioSocketChannelUnsafe 实例* sign_m_120 推送消息*/unsafe.flush();}}
  • io.netty.channel.AbstractChannel.AbstractUnsafe
    protected abstract class AbstractUnsafe implements Unsafe {// sign_m_120 推送消息@Overridepublic final void flush() {... // 省略校验outboundBuffer.addFlush();flush0(); // sign_m_121 推送消息}// sign_m_121 推送消息 (子类 AbstractNioUnsafe 重写,做了校验,但最终还是调用此方法)protected void flush0() {... // 省略校验try {doWrite(outboundBuffer); // sign_m_130 写入信道} ... // catch finally }}
  • io.netty.channel.socket.nio.NioSocketChannel
public class NioSocketChannel extends AbstractNioByteChannel implements io.netty.channel.socket.SocketChannel {// sign_m_130 写入信道@Overrideprotected void doWrite(ChannelOutboundBuffer in) throws Exception {SocketChannel ch = javaChannel();int writeSpinCount = config().getWriteSpinCount();do {... // 省略校验int maxBytesPerGatheringWrite = ((NioSocketChannelConfig) config).getMaxBytesPerGatheringWrite();ByteBuffer[] nioBuffers = in.nioBuffers(1024, maxBytesPerGatheringWrite);int nioBufferCnt = in.nioBufferCount();switch (nioBufferCnt) {case 0: ... // 略case 1: {ByteBuffer buffer = nioBuffers[0];int attemptedBytes = buffer.remaining();final int localWrittenBytes = ch.write(buffer); // 调用 Java 底层信道写入消息... // 省略其他in.removeBytes(localWrittenBytes); // 清空已发送的--writeSpinCount;break;}default: ... // 略}} while (writeSpinCount > 0);... // 略}
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

记录——随时更新

姓名&#xff1a;保密 生日&#xff1a;1998.01.09 民族&#xff1a;汉 爱好&#xff1a;吃 以下是我看过的&#xff0c;其中喜欢的&#xff0c;收集起来&#xff0c;以后有喜欢的还会添加&#xff0c;部分遗忘 电视剧 毒牙 非自然死亡(日剧) 校阅部女孩河野悦子(日剧) 失恋…

玩转STM32-直接存储器DMA(详细-慢工出细活)

文章目录 一、DMA介绍1.1 DMA简介1.2 DMA结构 二、DMA相关寄存器&#xff08;了解&#xff09;三、DMA的工作过程&#xff08;掌握&#xff09;四、DMA应用实例4.1 DMA常用库函数4.2 实例程序 一、DMA介绍 1.1 DMA简介 DMA用来提供外设与外设之间、外设与存储器之间、存储器与…

【算法】平衡二叉搜索树的左旋和右旋

树旋转是一种维护平衡树结构的重要操作&#xff0c;主要用于平衡二叉搜索树&#xff08;如AVL树和红黑树&#xff09;。树旋转分为左旋和右旋。 1. 树旋转的定义 左旋 (Left Rotation) 左旋操作将节点及其右子树进行调整&#xff0c;使其右子树的左子节点成为根节点&#xf…

有免费通配符证书吗?哪里可以申请?

市面上的免费SSL证书大多数为单域名证书&#xff0c;如果您的主域名拥有众多子域名&#xff0c;逐一申请单域名SSL证书不太现实&#xff0c;下面为介绍一款永久免费使用的通配符SSL证书申请流程 1 选择免费通配符证书提供商 免费通配符证书申请点击这里直接获取https://www.…

解决移动端使用el-drawer侧边栏展开时触摸滚动的问题

原因分析&#xff1a; 通过 el-drawer 控件实现了底部栏的展示和隐藏&#xff0c;但在移动设备上侧边栏展开时仍然可以通过触摸滑动页面内容&#xff0c;导致用户体验不佳&#xff0c;产生意外的滚动行为。 这是因为在底部栏展开时&#xff0c;未能有效阻止页面内容的触摸滑动…

分布式集群下的业务敏感数据加解密之具体业务解决方案(附代码)

前面的一篇文章中写了敏感数据加解密的通用解决方案&#xff0c;这篇文章来写一下具体的业务如何接入这个方案&#xff0c;业务的接入首要宗旨当然是对业务侵入性要最小&#xff0c;尽可能不影响原生的业务逻辑&#xff0c;说白了就是少改点代码。下面给大家提供一个简单的示例…

机械行业工程设计资质乙级技术负责人要求

机械行业工程设计资质乙级技术负责人的要求可以归纳为以下几点&#xff1a; 一、基本要求 学历&#xff1a;技术负责人应当具有大学本科以上学历。设计经历&#xff1a;技术负责人需要具有10年以上的设计经历。 二、项目经历要求 大型项目经验&#xff1a;技术负责人需要主…

redis 如何获取所有key的信息及值,相关过期时间查询

简单粗暴获取所有key keys * 另一种方式&#xff1a; scan 0 切换数据库&#xff1a; select db Map类型 获取map的数量 hlen key 获取map所有的数据 hvals key 或者 hgetall key 整个哈希表的过期时间&#xff1a; EXPIRE your_hash_key 3600 # 设置哈希表 yo…

前端渲染页面的原理

之前一直不愿意写一篇关于原理的&#xff0c;因为说起来实在是太繁杂&#xff0c;要写得细&#xff0c;码字梳理&#xff0c;计算下来起码都要差不多三周。以前一直躲避这个事情&#xff0c;现在反正有时间&#xff0c;为了不荒废自己&#xff0c;那就从头捋一遍。也方便自己后…

整理好了!2024年最常见 20 道 Rocket MQ面试题(四)

上一篇地址&#xff1a;整理好了&#xff01;2024年最常见 20 道 Rocket MQ面试题&#xff08;三&#xff09;-CSDN博客 七、RocketMQ消费模式有几种&#xff1f; RocketMQ 提供了两种主要的消费模式&#xff0c;分别是&#xff1a; 集群消费模式&#xff08;Clustering&…

HFish蜜罐实践:网络安全防御的主动出击

引言 随着网络攻击手段的不断演进&#xff0c;传统的被动防御策略已难以应对复杂多变的安全威胁。HFish蜜罐作为一种主动防御工具&#xff0c;通过模拟易受攻击的服务&#xff0c;吸引攻击者&#xff0c;不仅能有效捕获攻击行为&#xff0c;还能为安全分析和溯源提供宝贵信息。…

数据分析项目有哪些实施流程?揭示从数据准备到解决方案全过程

在当今数据驱动的商业环境中&#xff0c;数据分析项目的成功实施对于企业洞察市场趋势、优化产品服务、提升用户体验以及增强竞争力具有至关重要的作用。特别是对于直播类应用软件这样的快速增长领域&#xff0c;如何通过数据分析来扩大付费用户基础、提高用户留存率&#xff0…

音视频开发10 FFmpeg 内存模型-AVPacket, AVFrame

从现有的 Packet 拷贝一个新 Packet 的时候&#xff0c;有两种情况&#xff1a; • ①两个 Packet 的 buf 引用的是 同一数据缓存空间 &#xff0c;这时 候要注意数据缓存空间的释放问题&#xff1b; • ②两个 Packet 的 buf 引用不同的数据缓存空间 &#xff0c;每个 Pac…

矩阵结构下需要的文化导向

在产品研发与产品管理过程中&#xff0c;如何有效运行矩阵结构一直是企业面临的一大难题&#xff0c;尤其是在中国式官本位文化很强势的文化传统下。但是&#xff0c;这个难题是完全可以解决的&#xff0c;汉捷咨询在国内就已经帮助200多家企业建立了有效的矩阵结构。基于汉捷的…

2024年华为OD机试真题-项目排期-C++-OD统一考试(C卷D卷)

2024年OD统一考试(D卷)完整题库:华为OD机试2024年最新题库(Python、JAVA、C++合集) 题目描述: 项目组共有N个开发人员,项目经理接到了M个独立的需求,每个需求的工作量不同,且每个需求只能由一个开发人员独立完成,不能多人合作。假定各个需求直接无任何先后依赖关系,…

D2Admin:企业中后台产品前端集成方案的探索与实践

D2Admin&#xff1a;企业中后台产品前端集成方案的探索与实践 摘要&#xff1a;随着企业信息化建设的不断深入&#xff0c;中后台管理系统的前端技术选型与集成方案成为了关键。D2Admin作为一款完全开源免费的前端集成方案&#xff0c;通过采用最新的前端技术栈&#xff0c;提…

惠海半导体 30V-60V-100V-150VMOS管 打火机、加湿器NMOS管 高耐压

MOS管的工作原理 MOS管&#xff0c;即金属-氧化物-半导体场效应晶体管&#xff0c;是一种重要的电子元件&#xff0c;在电路中起着关键的作用。其工作原理主要基于半导体材料的特性以及电场对电荷的控制。 首先&#xff0c;MOS管的基本结构包括源极、栅极和漏极。其中&#xf…

我国赤泥年产量庞大 政策引导下赤泥绿色利用率将不断提升

我国赤泥年产量庞大 政策引导下赤泥绿色利用率将不断提升 赤泥是指从铝土矿中提炼氧化铝后产生的强碱性工业固体废渣&#xff0c;由于含大量氧化铁&#xff0c;表面呈现红色&#xff0c;而得名赤泥。   赤泥通常包含氧化铝、氧化铁、二氧化硅、氧化钙、碱金属及其他微量元素&…

HFish蜜罐管理端搭建:构建网络安全的主动防御系统

引言 在网络攻防对抗日益激烈的今天&#xff0c;蜜罐技术作为一种有效的主动防御手段&#xff0c;越来越受到网络安全专家的青睐。HFish蜜罐以其强大的功能和灵活的部署方式&#xff0c;成为网络安全防护体系中的重要组成部分。本文将详细介绍如何在CentOS 7.6系统上搭建HFish…