netty入门-4 Channel与ChannelFuture

devtools/2024/9/23 8:13:59/

Channel

基本类似于NIO中的Channel概念。作为读写数据的通道。
常见方法

  • close() 可以用来关闭 channel
  • closeFuture() 用来处理 channel 的关闭
    • sync 方法作用是同步等待 channel 关闭
    • addListener 方法是异步等待 channel 关闭
  • pipeline() 方法添加处理器
  • write() 方法将数据写入
  • writeAndFlush() 方法将数据写入并刷出

这些方法其中大多与NIO中的Channel一致。使用起来大同小异。

这里closeFuture是一个异步处理关闭结果的类。
如果我们直接使用close()方法关闭通道,它会异步的去进行关闭,直接执行后面的代码。
所以如果有操作希望在通道完全关闭后再进行就需要用这个closeFuture了。下面会介绍怎么用。

write方法,不一定立即发出消息。因为netty有一个缓冲机制,一般会等到消息积累一定大小再发送。所以writeAndFlush()方法的意义在于,不仅写到缓冲区,还要立即通过网络发送出去。

ChannelFuture

这个 ChannelFuture 是与Channel息息相关的类。
同时对于Future,学过一些并发编程的应该了解,是我们用来获取异步处理结果的类(同步阻塞等待)。
而这里的 ChannelFuture 类似于Future,它的目的是阻塞等待,或者添加异步回调来处理结果。
使用方法见下。
先看我们这段示例代码
在这里插入图片描述
我们观察截图中的代码。
可以看到用Bootstrap创建客户端时,链式调用到connect方法时返回的就是一个ChannelFuture对象。接下来的sync()channel方法自然就是ChannelFuture的方法了。顾名思义,sync()是同步等待结果,channel()是获取对应Channel。然后我们用拿到的Channel去做读写操作。

那么我们connect()方法为什么不能直接拿到Channel,而是要加这么一层ChannelFuture呢?
因为connect()网络操作,需要一定时间才能完成连接的建立,完成后才能返回对应连接的ChannelNetty所有操作都是异步的)。所以这个ChannelFuture就是用来等待连接结果的,就是一个异步结果的接收类,当connect()操作没完成时去获取Channel是获取不到的,所以调用sync等待异步操作connect()完成再调用channel()获取Channel

注意这里使用ChannelFuturesync的作用是让我们得线程对异步操作同步等待。
本段开头提到还有另一种方法处理异步结果,就是设置回调。即调用addListener方法给ChannelFuture添加一个监听器,并写好我们希望异步操作结束后进行什么操作,在异步操作结束后会触发监听器中我们写好的回调函数。
例子如下:

java">ChannelFuture channelFuture = new Bootstrap().group(new NioEventLoopGroup()).channel(NioSocketChannel.class).handler(new ChannelInitializer<Channel>() {@Overrideprotected void initChannel(Channel ch) {ch.pipeline().addLast(new StringEncoder());}}).connect("127.0.0.1", 8080);
System.out.println(channelFuture.channel()); // 1
channelFuture.addListener((ChannelFutureListener) future -> {System.out.println(future.channel()); // 2
});

这里的lambda表达式实际上是重写的ChannelFutureListener类中的operationComplete方法,这个方法会在异步操作完成后被调用,而它由我们重写,所以我们通过这种回调的方式来进行异步方法结果的处理。(具体怎么调用监听器里的方法不太清楚,需要看源码,估计实现应该不难,就是在操作结束后调一个方法。这里仅学习用法。后续我再去学习netty的源码)

同时Netty中除了connect的其他IO操作如writebindread等操作也是异步的,也可以用ChannelFuture来处理。

CloseFuture

ChannelFuture处理connectwrite等操作。
CloseFuture则是特殊的ChannelFuture。专门处理close操作

示例程序

java">@Slf4j
public class CloseFutureClient {public static void main(String[] args) throws InterruptedException {NioEventLoopGroup group new NioEventLoopGroup();ChannelFuture channelFuture = new Bootstrap().group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<NioSocketChannel>() {@Override // 在连接建立后被调用protected void initChannel(NioSocketChannel ch) throws Exception {ch.pipeline().addLast(new LoggingHandler(LogLevel.DEBUG));ch.pipeline().addLast(new StringEncoder());}}).connect(new InetSocketAddress("localhost", 8080));Channel channel = channelFuture.sync().channel();log.debug("{}", channel);new Thread(()->{Scanner scanner = new Scanner(System.in);while (true) {String line = scanner.nextLine();if ("q".equals(line)) {channel.close(); // close 异步操作 1s 之后
//                    log.debug("处理关闭之后的操作"); //此处不能做close操作完成后的处理,因为close是异步的,close没完成就会直接执行后面代码break;}channel.writeAndFlush(line);}}, "input").start();// 获取 CloseFuture 对象, 1) 同步处理关闭, 2) 异步处理关闭ChannelFuture closeFuture = channel.closeFuture();/*log.debug("waiting close...");closeFuture.sync();log.debug("处理关闭之后的操作");*/closeFuture.addListener(new ChannelFutureListener() {@Overridepublic void operationComplete(ChannelFuture future) throws Exception {log.debug("处理关闭之后的操作");group.shutdownGracefully();}});}
}

结语

老师这部分是Channel与ChannelFuture一起讲解使用,仅仅讲述了最基本的方法。

对于ChannelFuture的状态,偏内部机制的部分没有讲解。
且在紧接着的下部分讲解Future与Promise时也没有说到。

所以我打算这篇先按课程中的讲解,把最基本的使用摆上来。在下一篇对比分析Netty的Future与Promise时再考虑是否扩展偏底层的部分(我是初学者,扩展还需要自己看书或者找文章看,虽然已经看过了,但是写出来不免还是要费些时间精力的)。

感谢阅读,欢迎批评指正。


http://www.ppmy.cn/devtools/85072.html

相关文章

力扣爆刷第167天之TOP200五连刷101-105(二叉树序列化、验证IP、LFU)

力扣爆刷第167天之TOP200五连刷101-105&#xff08;二叉树序列化、验证IP、LFU&#xff09; 文章目录 力扣爆刷第167天之TOP200五连刷101-105&#xff08;二叉树序列化、验证IP、LFU&#xff09;一、224. 基本计算器二、297. 二叉树的序列化与反序列化三、283. 移动零四、468. …

Scrapy 爬取旅游景点相关数据(四)

本节内容主要为&#xff1a; &#xff08;1&#xff09;创建数据库 &#xff08;2&#xff09;创建数据库表 &#xff08;3&#xff09;爬取数据进MYSQL库 1 新建数据库 使用MYSQL数据库存储数据&#xff0c;创建一个新的数据库 create database scrapy_demo;2 新建数据表 CR…

vue3前端开发-小兔鲜项目-关于详情页图片渲染的一些技术

vue3前端开发-小兔鲜项目-关于详情页图片渲染的一些技术&#xff01;经过前面几天的努力&#xff0c;我们现在已经可以正常渲染产品详情了。是时候汇总一下&#xff0c;基础的技术知识点了。 1&#xff1a;单页面组件内的抽离&#xff0c;是一种很重要的思想。当我们遇到了&…

高清视频,无损音频,LDR6023——打造极致视听与高效充电的双重享受!

Type-C PD&#xff08;Power Delivery&#xff09;芯片是一种支持USB Type-C接口规范的电源管理单元&#xff0c;其主要功能包括&#xff1a; 快速充电&#xff1a;Type-C PD芯片支持高功率传输&#xff0c;能够提供更快的充电速度&#xff0c;使电子设备在短时间内充满电&…

科技与占星的融合:AI 智能占星师

本文由 ChatMoney团队出品 在科技的前沿领域&#xff0c;诞生了一位独特的存在——AI占星师。它并非传统意义上的占星师&#xff0c;而是融合了先进的人工智能技术与神秘的占星学知识。 这能够凭借其强大的数据分析能力和精准的算法&#xff0c;对星辰的排列和宇宙的能量进行深…

Docker容器逃逸漏洞-CVE-2024-21626

Snyk 在 Docker 引擎以及其他容器化技术(例如 Kubernetes)使用的 runc <=1.1.11 的所有版本中发现了一个漏洞。利用此问题可能会导致容器逃逸到底层主机操作系统,无论是通过执行恶意映像还是使用恶意 Dockerfile 或上游映像构建映像(即使用时FROM) CVE-2024-21626原理…

C#中GridControl的数据源双向绑定

1. 什么是双向数据绑定&#xff1f; 双向数据绑定是一种允许我们创建持久连接的技术&#xff0c;使模型数据和用户界面(UI)之间的交互能够自动同步。这意味着当模型数据发生变化时&#xff0c;UI会自动更新&#xff0c;反之亦然。这种双向数据绑定极大地简化了UI和模型数据之间…

鸿蒙仓颉语言【cryptocj 库】(介绍与SHA、MD5、HMAC摘要算法)

cryptocj 库 介绍 cryptocj 是一个安全的密码库&#xff0c;包括常用的密码算法、常用的密钥生成和签名验证。 该库是对 C 语言的 openSSL 封装的仓颉加密算法 1 提供SHA、MD5、HMAC摘要算法。 前置条件&#xff1a;NA 场景&#xff1a; OHOS&#xff0c; Linux&#xff…