上一篇我们通过一个简单的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的更多相关文章

  1. Netty:Channel 建立后消息发送失败

    1. 问题现象 Channel 建立后消息发送失败: ChannelFuture future = DeviceManager.getBootstrap().connect(); deviceChan ...

  2. Netty 源码解析(二):Netty 的 Channel

    本文首发于微信公众号[猿灯塔],转载引用请说明出处 接下来的时间灯塔君持续更新Netty系列一共九篇 Netty源码解析(一):开始 当前:Netty 源码解析(二): Netty 的 Channel ...

  3. Netty入门(二):Channel

    前言 Netty系列索引: 1.Netty入门(一):ByteBuf 2.Netty入门(二):Channel 在Netty框架中,Channel是其中之一的核心概念,是Netty网络通信的主体,由它 ...

  4. Netty:Netty的介绍以及它的核心组件(一)—— Channel

    1. Netty 介绍 Netty 是一个无阻塞的输入/输出(NIO)框架,它使开发低级网络服务器和客户端变得相对简单.Netty为需要在套接字级别上工作的开发人员提供了令人难以置信的强大功能,例如, ...

  5. Netty之Channel*

    Netty之Channel* 本文内容主要参考**<<Netty In Action>> ** 和Netty的文档和源码,偏笔记向. 先简略了解一下ChannelPipelin ...

  6. Go基础系列:channel入门

    Go channel系列: channel入门 为select设置超时时间 nil channel用法示例 双层channel用法示例 指定goroutine的执行顺序 channel基础 chann ...

  7. Go:channel

    一.channel 在 Go 语言里,不仅可以使用原子函数和互斥锁来保证对共享资源的安全访问以及消除竞争状态,还可以使用 channel,通过发送和接收需要共享的资源,在 goroutine 之间做同 ...

  8. Netty:一种非易失堵塞client/server相框

    Netty:一种非易失堵塞client/server相框 作者:chszs.转载需注明.博客主页:http://blog.csdn.net/chszs Netty是一个异步事件驱动的网络应用框架,为J ...

  9. Java NIO学习系列二:Channel

    上文总结了Java NIO中的Buffer相关知识点,本文中我们来总结一下它的好兄弟:Channel.上文有说到,Java NIO中的Buffer一般和Channel配对使用,NIO中的所有IO都起始 ...

随机推荐

  1. WEB渗透 - HTTP协议基础

    年初八 星灯花 https只能提高传输层安全 每一次客户端和服务端的通信都是独立的过程 cookie包括了sessionID和其他信息 重要的header S - C Set-Cookie:服务器发给 ...

  2. java中的对象 方法 引用 等一些抽象的概念是什么意思呢?

    2020-03-14 最近这一段时间有点忙,好久都没有更新博客了,之后我会一直坚持下去的,和大家一同进步的. 这段时间一直在学java,相信刚开始学习java的小白,刚开始接触那么些抽象的概念一定和我 ...

  3. PG归并排序算法详解

    前言 归并排序算法是连接算法中比较复杂的算法,相比嵌套循环与Hash匹配而言.本节会通过实例来说明该算法在PG中的具体实现. 在PG中,通过状态机来实现--归并-连接.当然这里的完整流程是排序--归并 ...

  4. vue-cli2.0项目 添加骨架屏

    1.创建项目 npm init webpack project 3.下载   vue-skeleton-webpack-plugin 插件 npm install vue-skeleton-webpa ...

  5. OPENGL图形渲染管线图解

    OPENGL固定图形渲染管线可以粗略地认为由下面的阶段衔接而成: 顶点颜色,光照,材质三个输入在光栅化前控制绘制管线的操作.光照和材质不能单独使用.顶点颜色,光源颜色,材质颜色都有alpha值,它们的 ...

  6. Windows Server 2012 R2 域证书服务搭建

    网管大叔说要给每个人颁发一个证书,这个证书很耗电 1.在服务器管理器中添加角色和功能 下一步 下一步 勾选Active Directory证书服务 下一步 下一步 勾选证书颁发机构,证书颁发机构Web ...

  7. JDBC 查询 模板

    JDBC 查询 与增删改不同的是SQL语句的不同,还有查询反回的是结果集  需要定义 利用 next()方法逐层查询数据 使用getXXX方法获取数据 代码相关参数根据个人设置进行修改!!!! pac ...

  8. search(3)- elastic4s-QueryDSL

    elastic4s是elasticsearch一个第三方开发的scala语言终端工具库(Elastic4s is a concise, idiomatic, reactive, type safe S ...

  9. Natas11 Writeup(常见编码、异或逆推、修改cookie)

    Natas11: 页面提示cookie被异或加密保护,查看源码,发现了一个预定义参数和三个函数. //预定义参数,猜测将showpassword设置为yes即可得到密码. $defaultdata = ...

  10. hGame2020第二周第一题题解

    Description: Cosmos通过两个小时速成了PHP+HTML,他信心满满的写了一个博客,他说要从博客后台开始......(flag在根目录, 禁止使用任何扫描器) Challenge Ad ...