Bytebuf(字节容器)

网络通信最终都是通过字节流进行传输的。 ByteBuf 就是 Netty 提供的一个字节容器,其内部是一个字节数组。 当我们通过 Netty 传输数据的时候,就是通过 ByteBuf 进行的。

我们可以将 ByteBuf 看作是 Netty 对 Java NIO 提供了 ByteBuffer 字节容器的封装和抽象。

有很多小伙伴可能就要问了 : 为什么不直接使用 Java NIO 提供的 ByteBuffer 呢?

因为 ByteBuffer 这个类使用起来过于复杂和繁琐。

Bootstrap 和 ServerBootstrap(启动引导类)

Bootstrap 是客户端的启动引导类/辅助类,具体使用方法如下:

        EventLoopGroup group = new NioEventLoopGroup();try {//创建客户端启动引导/辅助类:BootstrapBootstrap b = new Bootstrap();//指定线程模型b.group(group).......// 尝试建立连接ChannelFuture f = b.connect(host, port).sync();f.channel().closeFuture().sync();} finally {// 优雅关闭相关线程组资源group.shutdownGracefully();}

ServerBootstrap 客户端的启动引导类/辅助类,具体使用方法如下:

        // 1.bossGroup 用于接收连接,workerGroup 用于具体的处理EventLoopGroup bossGroup = new NioEventLoopGroup(1);EventLoopGroup workerGroup = new NioEventLoopGroup();try {//2.创建服务端启动引导/辅助类:ServerBootstrapServerBootstrap b = new ServerBootstrap();//3.给引导类配置两大线程组,确定了线程模型b.group(bossGroup, workerGroup).......// 6.绑定端口ChannelFuture f = b.bind(port).sync();// 等待连接关闭f.channel().closeFuture().sync();} finally {//7.优雅关闭相关线程组资源bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}

从上面的示例中,我们可以看出:

  1. Bootstrap 通常使用 connet() 方法连接到远程的主机和端口,作为一个 Netty TCP 协议通信中的客户端。另外,Bootstrap 也可以通过 bind() 方法绑定本地的一个端口,作为 UDP 协议通信中的一端。
  2. ServerBootstrap通常使用 bind() 方法绑定本地的端口上,然后等待客户端的连接。
  3. Bootstrap 只需要配置一个线程组— EventLoopGroup ,而 ServerBootstrap需要配置两个线程组— EventLoopGroup ,一个用于接收连接,一个用于具体的 IO 处理。

Channel(网络操作抽象类)

Channel 接口是 Netty 对网络操作抽象类。通过 Channel 我们可以进行 I/O 操作。

一旦客户端成功连接服务端,就会新建一个 Channel 同该用户端进行绑定,示例代码如下:

   //  通过 Bootstrap 的 connect 方法连接到服务端public Channel doConnect(InetSocketAddress inetSocketAddress) {CompletableFuture<Channel> completableFuture = new CompletableFuture<>();bootstrap.connect(inetSocketAddress).addListener((ChannelFutureListener) future -> {if (future.isSuccess()) {completableFuture.complete(future.channel());} else {throw new IllegalStateException();}});return completableFuture.get();}

比较常用的Channel接口实现类是 :

  • NioServerSocketChannel(服务端)
  • NioSocketChannel(客户端)

这两个 Channel 可以和 BIO 编程模型中的ServerSocket以及Socket两个概念对应上。

EventLoop(事件循环)

EventLoop 介绍

这么说吧!EventLoop(事件循环)接口可以说是 Netty 中最核心的概念了!

《Netty 实战》这本书是这样介绍它的:

EventLoop 定义了 Netty 的核心抽象,用于处理连接的生命周期中所发生的事件。

是不是很难理解?说实话,我学习 Netty 的时候看到这句话是没太能理解的。

说白了,EventLoop 的主要作用实际就是责监听网络事件并调用事件处理器进行相关 I/O 操作(读写)的处理。

Channel 和 EventLoop 的关系

ChannelEventLoop 直接有啥联系呢?

Channel 为 Netty 网络操作(读写等操作)抽象类,EventLoop 负责处理注册到其上的Channel 的 I/O 操作,两者配合进行 I/O 操作。

EventloopGroup 和 EventLoop 的关系

EventLoopGroup 包含多个 EventLoop(每一个 EventLoop 通常内部包含一个线程),它管理着所有的 EventLoop 的生命周期。

并且,EventLoop 处理的 I/O 事件都将在它专有的 Thread 上被处理,即 ThreadEventLoop 属于 1 : 1 的关系,从而保证线程安全。

下图是 Netty NIO 模型对应的 EventLoop 模型。通过这个图应该可以将EventloopGroupEventLoopChannel三者联系起来。

https://www.jianshu.com/p/128ddc36e713

ChannelHandler(消息处理器) 和 ChannelPipeline(ChannelHandler 对象链表)

下面这段代码使用过 Netty 的小伙伴应该不会陌生,我们指定了序列化编解码器以及自定义的 ChannelHandler 处理消息。

        b.group(eventLoopGroup).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) {ch.pipeline().addLast(new NettyKryoDecoder(kryoSerializer, RpcResponse.class));ch.pipeline().addLast(new NettyKryoEncoder(kryoSerializer, RpcRequest.class));ch.pipeline().addLast(new KryoClientHandler());}});

ChannelHandler 是消息的具体处理器,主要负责处理客户端/服务端接收和发送的数据。

Channel 被创建时,它会被自动地分配到它专属的 ChannelPipeline。 一个Channel包含一个 ChannelPipelineChannelPipelineChannelHandler 的链,一个 pipeline 上可以有多个 ChannelHandler

我们可以在 ChannelPipeline 上通过 addLast() 方法添加一个或者多个ChannelHandler一个数据或者事件可能会被多个 Handler 处理) 。当一个 ChannelHandler 处理完之后就将数据交给下一个 ChannelHandler

ChannelHandler 被添加到的 ChannelPipeline 它得到一个 ChannelHandlerContext,它代表一个 ChannelHandlerChannelPipeline 之间的“绑定”。 ChannelPipeline 通过 ChannelHandlerContext来间接管理 ChannelHandler

https://www.javadoop.com/post/netty-part-4

ChannelFuture(操作执行结果)

public interface ChannelFuture extends Future<Void> {Channel channel();ChannelFuture addListener(GenericFutureListener<? extends Future<? super Void>> var1);......ChannelFuture sync() throws InterruptedException;
}

Netty 是异步非阻塞的,所有的 I/O 操作都为异步的。

因此,我们不能立刻得到操作是否执行成功,但是,你可以通过 ChannelFuture 接口的 addListener() 方法注册一个 ChannelFutureListener,当操作执行成功或者失败时,监听就会自动触发返回结果。

ChannelFuture f = b.connect(host, port).addListener(future -> {if (future.isSuccess()) {System.out.println("连接成功!");} else {System.err.println("连接失败!");}
}).sync();

并且,你还可以通过ChannelFuturechannel() 方法获取连接相关联的Channel

Channel channel = f.channel();

另外,我们还可以通过 ChannelFuture 接口的 sync()方法让异步的操作编程同步的。

//bind()是异步的,但是,你可以通过 `sync()`方法将其变为同步。
ChannelFuture f = b.bind(port).sync();

【Netty】大白话 Netty 核心组件分析相关推荐

  1. 【Netty】Netty 核心组件 ( ChannelPipeline 中的 ChannelHandlerContext 双向链表分析 )

    文章目录 一. 代码示例分析 二. ChannelHandlerContext 双向链表类型 三. Pipeline / ChannelPipeline 管道内双向链表分析 四. 数据入站与出站 接上 ...

  2. 【Netty】Netty 核心组件 ( ChannelHandlerContext )

    文章目录 一. ChannelHandlerContext 组件 二. ChannelHandlerContext 组件 debug 调试 三. ChannelHandlerContext 组件 de ...

  3. 【Netty】IO 模型简介 ( Netty 特点 | Netty 应用场景 | Java 三种 IO 模型 | BIO 模型 )

    文章目录 I . Netty 简介 II . Netty 应用场景 III . Java I/O 模型 IV . BIO 概念 V . BIO 开发流程 VI . BIO 实例 VII . BIO 模 ...

  4. 【Netty】Netty 简介 ( 原生 NIO 弊端 | Netty 框架 | Netty 版本 | 线程模型 | 线程 阻塞 IO 模型 | Reactor 模式引入 )

    文章目录 一. NIO 原生 API 弊端 二. Netty 简介 三. Netty 架构 四. Netty 版本 五. Netty 线程模型 六. 阻塞 IO 线程模型 七. 反应器 ( React ...

  5. Netty自学-Netty学习(一)

    什么Netty? Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. 关注公众号,我们一 ...

  6. 【初识Netty使用Netty实现简单的客户端与服务端的通信操作Netty框架中一些重要的类以及方法的解析】

    一.Netty是什么? Netty 由 Trustin Lee(韩国,Line 公司)2004 年开发 本质:网络应用程序框架 实现:异步.事件驱动 特性:高性能.可维护.快速开发 用途:开发服务器和 ...

  7. SpringBoot2+Netty+WebSocket(netty实现websocket)

    ##### 一.SpringBoot2+Netty+WebSocket(netty实现websocket,支持URL参数) 原文链接: https://zhengkai.blog.csdn.net/a ...

  8. Netty Channel源码分析

    原文:https://wangwei.one/posts/netty-channel-source-analyse.html 前面,我们大致了解了Netty中的几个核心组件.今天我们就来先来介绍Net ...

  9. Netty Pipeline源码分析(2)

    原文链接:https://wangwei.one/posts/net... 前面 ,我们分析了Netty Pipeline的初始化及节点添加与删除逻辑.接下来,我们将来分析Pipeline的事件传播机 ...

最新文章

  1. oracle收集统计计划,oracle收集统计信息之analyze
  2. Struts 2的基石——拦截器(Interceptor)
  3. @property和@setter和@getter
  4. php input 数组的值,如何获取2值表单输入数组到PHP数组中(How to get 2 value form input array into PHP array)...
  5. SSIS 学习(2):数据流任务(上)
  6. 卡通驱动项目ThreeDPoseTracker——模型驱动解析
  7. JavaScript语义基础
  8. 微软开源P语言,实现安全的异步事件驱动编程
  9. IntelliJ IDEA for Mac 彻底卸载/彻底删除
  10. 【C++ grammar】引用
  11. J2EE WEBWORK FRAMEWORK安全隐患
  12. mysql 开启事务_MySQL可重读隔离级别的底层实现原理
  13. CABasicAnimation 使用
  14. protected的继承方式有什么特点_草莓的授粉方式有哪些?各有什么特点
  15. Linux内核4.17再获捷报
  16. c语言邻接表存储拓扑排序,拓扑排序(完整案列及C语言完整代码实现)
  17. 三层交换机配置的步骤
  18. 千兆路由器怎么设置网速最快_千兆路由器怎么设置才能发挥最好【图】
  19. 怎么将英文的PDF翻译成中文的
  20. D3.js学习笔记七:多系列折线图与图例

热门文章

  1. 人类是怎么从猩猩身上惹来艾滋病的?人与兽的关系很单纯!
  2. 0与1c语言编译,C语言程序设计(07776-1)第11章编译预处理课案.ppt
  3. R语言ggplot2可视化分面图、在分面图中的每个直方图中添加均值文本标签、添加均值红色竖线
  4. R语言ggplot2可视化条形图可视化控制底部和x轴之间没有空格实战:即条形图的底部直接和坐标轴连接
  5. R语言将dataframe长表转化为宽表实战:使用reshape函数、使用tidyr包的spread函数、使用data.table
  6. Error in do_one(nmeth) : NA/NaN/Inf in foreign function call (arg 1)
  7. python使用fpdf生成数据报告pdf文件
  8. 长连接、短连接、短轮询、长轮询
  9. python使用imbalanced-learn的RepeatedEditedNearestNeighbours方法进行下采样处理数据不平衡问题
  10. python进行探索性数据分析EDA(Exploratory Data Analysis)分析