文章目录

  • 简介
  • Channel详解
    • 异步IO和ChannelFuture
    • Channel的层级结构
    • 释放资源
    • 事件处理
  • 总结

简介

Channel是连接ByteBuf和Event的桥梁,netty中的Channel提供了统一的API,通过这种统一的API,netty可以轻松的对接多种传输类型,如OIO,NIO等。今天本文将会介绍Channel的使用和Channel相关的一些概念。

Channel详解

Channel是什么? Channel是一个连接网络输入和IO处理的桥梁。你可以通过Channel来判断当前的状态,是open还是connected,还可以判断当前Channel支持的IO操作,还可以使用ChannelPipeline对Channel中的消息进行处理。

先看下Channel的定义:

public interface Channel extends AttributeMap, ChannelOutboundInvoker, Comparable<Channel> {

可以看到Channel是一个接口,它继承了AttributeMap, ChannelOutboundInvoker, Comparable三个类。Comparable表示这个类可以用来做比较。AttributeMap用来存储Channel的各种属性。ChannelOutboundInvoker主要负责Channel和外部 SocketAddress 进行连接和对写。

再看下channel中定义的方法:

可以看出channel中定义的方法是多种多样的,这些方法都有些什么特点呢?接下来一一为您讲解。

异步IO和ChannelFuture

netty中所有的IO都是异步IO,也就是说所有的IO都是立即返回的,返回的时候,IO可能还没有结束,所以需要返回一个ChannelFuture,当IO有结果之后,会去通知ChannelFuture,这样就可以取出结果了。

ChannelFuture是java.util.concurrent.Future的子类,它除了可以拿到线程的执行结果之外,还对其进行了扩展,加入了当前任务状态判断、等待任务执行和添加listener的功能。

其他的功能都很好理解,它的突破在于可以对ChannelFuture添加listener,我们列出一个添加listener的方法:

Future<V> addListeners(GenericFutureListener<? extends Future<? super V>>... listeners);

添加的Listener会在future执行结束之后,被通知。不需要自己再去调用get等待future结束。这里实际上就是异步IO概念的实现,不需要主动去调用,当你完成之后来通知我就行。非常的美好!

ChannelFuture 有两个状态:uncompleted或者completed,分别代表任务的执行状态。

当一个IO刚开始的时候,返回一个ChannelFuture对象,这个对象的初始状态是uncompleted。注意,这个状态下的IO是还未开始工作的状态。当IO完成之后,不管是succeeded, failed 或者 cancelled状态,ChannelFuture的状态都会转换成为completed。

下图展示的是ChannelFuture状态和IO状态的对应图:

如果要监控IO的状态,可以使用上面我们提到的 addListener 方法,为ChannelFuture添加一个ChannelFutureListener。

如果要等待IO执行完毕,还有一个await()方法,但是这个方法会去等待IO执行完毕,是一个同步的方法,所以并不推荐。

相比而言,addListener(GenericFutureListener)是一个非阻塞的异步方法,将会把一个ChannelFutureListener添加到ChannelFuture中,当IO结束之后会自动通知ChannelFutureListener,非常好用。

对于处理IO操作的ChannelHandler来说,为了避免IO的阻塞,一定不要在ChannelHandler的IO方法中调用await(),这样有可能会导致ChannelHandler因为IO阻塞导致性能下降。

下面举两个例子,一个是错误的操作,一个是正确的操作:

   // 错误操作@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {ChannelFuture future = ctx.channel().close();future.awaitUninterruptibly();// 调用其他逻辑}// 正确操作@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) {ChannelFuture future = ctx.channel().close();future.addListener(new ChannelFutureListener() {public void operationComplete(ChannelFuture future) {// 调用其他逻辑}});}

大家可以对比下上面两种写法的区别。

另外要注意的是ChannelFuture中的这些await方法比如:await(long), await(long, TimeUnit), awaitUninterruptibly(long), 或者 awaitUninterruptibly(long, TimeUnit)可以带一个过期时间,大家要注意的是这个过期时间是等待IO执行的时间,并不是IO的timeout时间,也就是说当await超时之后,IO还有可能没有执行完成,这就导致了下面的代码有可能报错:

   Bootstrap b = ...;ChannelFuture f = b.connect(...);f.awaitUninterruptibly(10, TimeUnit.SECONDS);if (f.isCancelled()) {// 用户取消了Channel} else if (!f.isSuccess()) {// 这里可能会报异常,因为底层的IO可能还没有执行完成f.cause().printStackTrace();} else {// 成功建立连接}

上面的代码可以改成下面的例子:

  Bootstrap b = ...;// 配置连接timeout的时间b.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000);ChannelFuture f = b.connect(...);f.awaitUninterruptibly();// 等待直到底层IO执行完毕assert f.isDone();if (f.isCancelled()) {// 用户手动取消Channel} else if (!f.isSuccess()) {f.cause().printStackTrace();} else {// 成功建立连接}

Channel的层级结构

netty中的Channel是有层级结构的,通过parent属性可获取这种层级结构。parent获取的对象和Channel的创建方式有关。比如如果是一个被ServerSocketChannel accepted的SocketChannel,那么它的parent就是ServerSocketChannel。

释放资源

和所有的IO一样,Channel在用完之后也需要被释放,需要调用close()或者close(ChannelPromise) 方法。

事件处理

channel负责建立连接,建立好的连接就可以用来处理事件ChannelEvent了,实际上ChannelEvent是由定义的一个个Channelhandler来处理的。而ChannelPipeline就是连接channel和channelhandler的桥梁。

我们将会下下一章详细讲解ChannelEvent、Channelhandler和ChannelPipeline的关联关系,敬请期待。

总结

Channel在netty中是做为一个关键的通道而存在的,后面的Event和Handler是以channel为基础运行的,所以说Channel就是netty的基础,好了,今天的介绍到这里就结束了,敬请期待后续的文章。

本文已收录于 http://www.flydean.com/04-netty-channel/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

netty系列之:netty中的Channel详解相关推荐

  1. 【Linux系列】Linux中dmesg命令详解

    DATE: 2019-5-15 文章目录 前言 1.参考 2.dmesg命令详解 3.dmesg实例 3.1. 列出加载到内核中的所有驱动 3.2. 列出所有被检测到的硬件 3.3.清空dmesg缓冲 ...

  2. NIO中的Channel详解

    NIO的通道类似于流,但有些区别如下: •通道可以同时进行读写,而流只能读或者只能写 •通道可以实现异步读写数据 •通道可以从缓冲区(Buffer)读数据,也可以写数据到缓冲区 BIO 中的 stre ...

  3. Netty网络编程(三):Channel详解

    文章目录 简介 Channel详解 异步IO和ChannelFuture Channel的层级结构 释放资源 事件处理 总结 简介 Channel是连接ByteBuf和Event的桥梁,netty中的 ...

  4. 【读后感】Netty 系列之 Netty 高性能之道 - 相比 Mina 如何 ?

    [读后感]Netty 系列之 Netty 高性能之道 - 相比 Mina 如何 ? 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商 ...

  5. FLV文件中VideoPacket的详解

    FLV文件中VideoPacket的详解 众所周知,FLV文件体主要有三种Tag组成:AUDIODATA.VIDEODATA和SCRIPTDATA,其中SCRIPTDATA中包含了MetaData,通 ...

  6. 【深度学习系列】卷积神经网络CNN原理详解(一)——基本原理(1)

    上篇文章我们给出了用paddlepaddle来做手写数字识别的示例,并对网络结构进行到了调整,提高了识别的精度.有的同学表示不是很理解原理,为什么传统的机器学习算法,简单的神经网络(如多层感知机)都可 ...

  7. Go Channel 详解

    原文链接:Go Channel 详解 Channel类型 Channel类型的定义格式如下: ChannelType = ( "chan" | "chan" & ...

  8. python的抽象类详解_第7.19节 Python中的抽象类详解:abstractmethod、abc与真实子类...

    第7.19节 Python中的抽象类详解:abstractmethod.abc与真实子类 一. 引言 前面相关的章节已经介绍过,Python中定义某种类型是以实现了该类型对应的协议为标准的,而不是以继 ...

  9. Python-Matplotlib可视化(番外篇)——Matplotlib中的事件处理详解与实战

    Python-Matplotlib可视化(番外篇)--Matplotlib中的事件处理详解与实战 前言 事件连接 事件属性 实战1:直方图中矩形的拖拽 实战2:鼠标进入和离开 相关链接与参考 前言 在 ...

最新文章

  1. 28笔记本USB接口案例分析
  2. 经典C语言程序100例之三四
  3. 02_3中方式的反射,通过Class.forName获得Class对象,通过类.class获得字节码对象,通过类实例.getClass()的方式获得Class对象
  4. 常用的Linux命令组合
  5. 编程随想 关系图_支持PLC编程的5大语言,全部会用的才是大神!
  6. bzoj 3385: [Usaco2004 Nov]Lake Counting 数池塘(DFS)
  7. sql表达式_SQL表达式
  8. 【计算机视觉】pycharm自制一个吉他扒谱软件(附源码)
  9. 保定工程技术学校网络计算机,保定工程技术学校2021年有哪些专业
  10. IIS服务器重启三种方法
  11. SpringBoot整合oracle报错异常信息(java.lang.AbstractMethodError: oracle.jdbc.driver.T4CConnection.isValid(I))
  12. 华为--NAT技术easy IP 原理配置or实验详解
  13. mysql数据库教程外联_活字格外联数据库SQLServer和Mysql的经验(大多数经验也适合其它使用外联数据库的平台)...
  14. 关于高德地图的分析报告
  15. Eclipse插件Target Management (RSE)
  16. TI快充芯片-BQ25890
  17. 异常:com.alibaba.druid.sql.parser.ParserException: ERROR. token : DESC, pos : 72
  18. numpy取数组中的行和列
  19. UbuntuKylin引领我们走上开放创新之路
  20. 漫步线性代数八——向量空间和子空间

热门文章

  1. 深度优先遍历算法-03二叉树路径遍历问题
  2. 字符串Hash的原理与应用
  3. HDU4273(求三维凸包重心到表面的最短距离)
  4. cometoj contest 6(记录型博客)
  5. 直接将自身代码注入傀儡进程
  6. base64编解码的类
  7. 多线程执行CPU过高问题
  8. MFC拖拽文件到任意EDIT控件
  9. STL学习之一(栈(statck))
  10. WebRTC 的版本号与代码分支