Netty:Channel
上一篇我们通过一个简单的Netty代码了解到了Netty中的核心组件,这一篇我们将围绕核心组件中的Channel来展开学习。
Channel的简介
Channel代表着与网络套接字或者能够进行IO操作(read、write、connect或者bind)的组件的联系,一个Channel向用户提供了如下内容:
1、Channel当前的状态,比如是否打开、是否连接;
2、Channel的配置参数,比如接收缓冲区的大小;
3、Channel支持的IO操作(read、write、connect或者bind);
4、用于支持处理与Channel关联的所有IO事件和请求的ChannelPipeline组件。
Netty中的所有IO操作都是异步的。这意味着任何IO调用都将立即返回,而不能保证所请求的IO操作在调用结束时完成。相反,将返回一个带有ChannelFuture的实例,该实例将在请求的IO操作成功、失败或取消时通知应用。
Channel可以具有父级,具体取决于其创建方式。例如,SocketChannel在ServerSocketChannel接受它时,通过parent()方法将ServerSocketChannel作为它的父级返回。层次结构的语义取决于Channel所属的传输实现。例如,可以编写一个新的Channel实现,以创建共享一个套接字连接的子通道,就像BEEP和SSH一样。
某些传输公开了特定于该传输的其他操作,可以将Channel向下转换为子类型以调用此类操作。例如,对于旧的IO数据报传输,DatagramChannel提供了join /leave操作。
一旦使用完Channel,调用close()或close(ChannelPromise)释放资源就显得尤为重要,这样做可以确保以适当的方式(即文件句柄)释放所有资源。
Channel的方法
学习Channel提供的方法,其实可以结合上述简介部分来看。
比如,有关Channel的状态,我们可以看到这几个方法:
是否打开看isOpen方法,是否注册到EventLoop看isRegistered方法,是否连接看isActive方法。
Channel的配置参数方法可以看config方法:
该方法返回了ChannelConfig对象,这个接口定义了Channel的配置参数集合,但是在实际应用中,需结合实际的传输协议来设置具体的ChannelConfig,比如对于TCP/IP协议,需要具体被设置的对象就是SocketChannelConfig。
通过pipeline()方法,可以获取到Channel的ChannelPipeline对象,正如上文所述,ChannelPipeline也是Netty的核心组件,它可以理解为是ChannelHandler的容器,用于处理Channel的所有事件。
简介中提到了Netty异步操作会返回ChannelFuture对象,那么在Channel所提供的方法中是如何体现和这个对象的交互的呢?答案就是我们可以从closeFuture()方法中看到ChannelFuture对象,这个方法告诉我们Channel关闭时将返回用于通知的ChannelFuture,只有Channel真正的被关闭完成后,才会通过ChannelFuture回调通知到应用。
关于ChannelPipeline、ChannelHandler和ChannelFuture,我们将在后续的文章中学习。
除了上述方法,Channel还有很多方法,比如:
每一个Channel都可以有自己的id,ChannelId有2个主要的方法,asShortText()会返回短的但是全局不唯一的标识符,asLongText()会返回长的同时全局唯一的标识符。
eventLoop()会返回Channel所注册之上的EventLoop,EventLoop也是Netty的核心组件,我们也将在后续的文章中学习。
parent()会返回Channel的父级,如果没有父级则返回null。
另外Channel中还有一个内部类Unsafe,这个类的方法不建议外部使用,仅限于Netty内部使用。
源码流程
以服务端为例,在我们服务端DEMO中,可以看到代码中并未显式的创建Channel和将Channel注册到EventLoop,那么服务端启动时是如何创建Channel及将Channel注册到EventLoop呢?让我们一起来看下启动的源代码,一窥究竟。
首先,在Server中调用的是bind方法,bind里面调用的是doBind。
在doBind中,进入了启动的核心逻辑initAndRegister。
initAndRegister,顾名思义,就是初始化和注册,初始化前就有Channel的创建,注册里面包含了Channel注册到EventLoop的过程。
让我们继续看Channel是如何创建的,调用了ReflectiveChannelFactory的newChannel方法,是通过反射的方式来创建的Channel。
进入到我们的DemoServer中的NioServerSocketChannel,继续查看它的构造方法。
经过一步一步的跟进,可以在AbstractChannel看到Channel的构造过程,在这个方法中,我们可以看到熟悉的id、parent、unsafe和pipeline,这些都是Channel中的关键属性或者对象。
创建完成后,先忽略初始化,咱们再来看下Channel是如何注册的?我们来看config().group().register(channel)。
先来看下next()方法返回的是什么?
最后可以发现next()方法返回的是SingleThreadEventLoop,其实到这一步我们也可以知道Netty中的MultithreadEventLoopGroup里面可以获取到很多SingleThreadEventLoop,而SingleThreadEventLoop是一个单线程任务执行的事件循环,在它的父类SingleThreadEventExecutor中我们可以找到这个Thread。
继续看register方法。
最后会进入到真正的执行注册的AbstractUnsafe类的register0方法中。
进一步跟进,调用doRegister方法。
最终会进入到AbstractNioChannel的doRegister方法。在这里我们可以看到NIO的身影,比如SelectionKey、Selector等。到这里,我们就可以看到Channel是如何注册到NioEventLoop,它的底层本质也就是NIO中的Channel注册到Selector,因为在NioEventLoop中集成了一个Selector。
至此,我们已经知道了Channel的创建和注册的过程。
最后总结一下:
1、服务端这块,Channel创建的过程是通过反射来创建的,最终是进入到了AbstractChannel的构造函数中;
2、服务端这块,Channel注册到EventLoop的过程,本质上也就是NIO中的Channel注册到Selector的过程;
3、看源码的过程中,其实还有很多有意思的细节,比如创建Channel的同时其实ChannelPipeline也创建好了,注册的时候其实会判断注册线程和当前线程是不是一个线程来看是立即注册还是新起线程注册?这些后面再来进一步的学习和分析。
Netty:Channel的更多相关文章
- Netty:Channel 建立后消息发送失败
1. 问题现象 Channel 建立后消息发送失败: ChannelFuture future = DeviceManager.getBootstrap().connect(); deviceChan ...
- Netty 源码解析(二):Netty 的 Channel
本文首发于微信公众号[猿灯塔],转载引用请说明出处 接下来的时间灯塔君持续更新Netty系列一共九篇 Netty源码解析(一):开始 当前:Netty 源码解析(二): Netty 的 Channel ...
- Netty入门(二):Channel
前言 Netty系列索引: 1.Netty入门(一):ByteBuf 2.Netty入门(二):Channel 在Netty框架中,Channel是其中之一的核心概念,是Netty网络通信的主体,由它 ...
- Netty:Netty的介绍以及它的核心组件(一)—— Channel
1. Netty 介绍 Netty 是一个无阻塞的输入/输出(NIO)框架,它使开发低级网络服务器和客户端变得相对简单.Netty为需要在套接字级别上工作的开发人员提供了令人难以置信的强大功能,例如, ...
- Netty之Channel*
Netty之Channel* 本文内容主要参考**<<Netty In Action>> ** 和Netty的文档和源码,偏笔记向. 先简略了解一下ChannelPipelin ...
- Go基础系列:channel入门
Go channel系列: channel入门 为select设置超时时间 nil channel用法示例 双层channel用法示例 指定goroutine的执行顺序 channel基础 chann ...
- Go:channel
一.channel 在 Go 语言里,不仅可以使用原子函数和互斥锁来保证对共享资源的安全访问以及消除竞争状态,还可以使用 channel,通过发送和接收需要共享的资源,在 goroutine 之间做同 ...
- Netty:一种非易失堵塞client/server相框
Netty:一种非易失堵塞client/server相框 作者:chszs.转载需注明.博客主页:http://blog.csdn.net/chszs Netty是一个异步事件驱动的网络应用框架,为J ...
- Java NIO学习系列二:Channel
上文总结了Java NIO中的Buffer相关知识点,本文中我们来总结一下它的好兄弟:Channel.上文有说到,Java NIO中的Buffer一般和Channel配对使用,NIO中的所有IO都起始 ...
随机推荐
- 实验二——Linux系统简单文件操作命令
项目 内容 这个作业属于那个课程 这里是链接 作业要求在哪里 这里是链接 学号-姓名 17041506-张政 作业学习目标 学习在Linux系统终端下进行命令行操作,掌握常用命令行操作并能通过命令行操 ...
- 网络|N1盒子做旁路由刷OpenWRT系统(小白专用)
N1盒子做旁路由刷OpenWRT系统(小白专用) 为什么要用N1盒子 现如今新上市的路由器,市面上能买到的300元以内的路由器大多数都是双频(5G Hz和2.4G Hz)和几年前相比无论是速度还是性能 ...
- Spring总结————spring核心Core
一.spring的概念 spring是一个开源的,轻量级控制反转和面向切面的容器框架,解决企业应用开发的复杂性,降低耦合,更易于测试. spring春天.如果写一个小的项目,我们可以在项目中想创建一个 ...
- Mybatis(一)Mybatis相关概念
1.1 传统的JDBC实现 public static void main(String[] args) { Connection connetion = null; PreparedStatemen ...
- 是的,GitHub APP 终于上线了
是的,全球最大程序员社交网站的 App 今天正式上线了,早在 GitHub 2019 开发者大会说要出的客户端,那会儿还需要申请. 兴致勃勃去申请了,然后就是等,这一等就是四五月,黄花菜都凉了,今天终 ...
- vmware导入ova文件踩坑记
问题来源 众所周知,所有的网络行为都会产生相应的网络流量,那么所有的网络攻击行为也有其对应的流量特点,那么是否能根据流量特点进而分析出其对应的是什么攻击行为呢? 我在虚拟机上使用vulnhub的靶场环 ...
- Journal of Proteome Research | Quantitative Subcellular Proteomics of the Orbitofrontal Cortex of Schizophrenia Patients (精神分裂症病人眶额叶皮层亚细胞结构的定量蛋白质组学研究)(解读人:王聚)
期刊名:Journal of Proteome Research 发表时间:(2019年10月) IF:3.78 单位: 里约热内卢联邦大学 坎皮纳斯州立大学 坎皮纳斯州立大学神经生物学中心 卡拉博大 ...
- vscode回车补全代码
VsCode设置回车补全代码而不换行 有一部分人不习惯用tab键补全代码,我就是其中之一,习惯了回车补全的我决定设置一波,网上找了很多, 没找到比较详细的,所以自己写一个 有一个叫keybinding ...
- css3实现旋转卡片
基本思路:父div使用相对定位包裹着两个子元素,子元素使用绝对定位,定位在同一个位置,初始时一个div翻转到后面隐藏,另一个在前面显示,当鼠标悬停在父元素上时,前面的子元素旋转180度,到背面隐藏:背 ...
- JavaScript----简介及基础语法
##JavaScript *概念:一门客户端脚本语言 *运行在客户端浏览器中的.每一个浏览器都有JavaScript的解析引擎. *脚本语言:不需要编译,直接就可以被浏览器解析执行. *功能: *可以 ...