从ChannelPipeline的传输的事件类型角度,Netty的事件可以分为Inbound和Outbound事件。
Inbound事件是一个通知事件,当某件事已经发生了,然后通过Inbound事件进行通知,Inbound通常发生在Channel的状态的改变或IO事件就绪
Outbound事件都是请求事件, 请求某件事情的发生, 然后通过Outbound事件进行通知。
作用:触发事件告知Inbound ChannelHandler:ChannelHandlerContext的Channel注册于其EventLoop,调用ChannelInboundHandler的channelRegistered
作用:触发事件告知Inbound ChannelHandler:ChannelHandlerContext的Channel现在处于活动状态,调用ChannelInboundHandler的channelActive
作用:触发事件告知Inbound ChannelHandler:当前Channel正在从对等方读取消息,调用ChannelInboundHandler的channelRead。
作用:触发事件告知Inbound ChannelHandler:当前读操作读取的最后一条消息被channelRead(ChannelHandlerContext, Object)}使用,调用ChannelInboundHandler的channelReadComplete。
作用:触发事件告知Inbound ChannelHandler:抛出Throwable异常,调用ChannelInboundHandler的exceptionCaught。
作用:触发事件告知Inbound ChannelHandler:用户事件正在触发,调用ChannelInboundHandler的userEventTriggered。
作用:触发事件告知Inbound ChannelHandler:Channel的可写状态发生更改,调用ChannelInboundHandler的channelWritabilityChanged。
作用:触发事件告知Inbound ChannelHandler:ChannelHandlerContext的Channel现在是不活动的,并已达到其生命周期的结束,调用ChannelInboundHandler的channelInactive
作用:触发事件告知Inbound ChannelHandler:ChannelHandlerContext的Channel从其EventLoop注销,调用ChannelInboundHandler的channelUnregistered
作用:请求绑定到给定的SocketAddress,并在操作完成后通知ChannelFuture,原因可能是操作成功,也可能是错误,调用ChannelOutboundHandler的bind
作用:请求连接到给定的SocketAddress,并在操作完成后通知ChannelFuture,原因可能是操作成功,也可能是错误,调用ChannelOutboundHandler的connect
作用:请求通过这个ChannelHandlerContext通过ChannelPipeline写入消息。此方法不会请求实际刷新,因此请确保在希望请求将所有挂起数据刷新到实际传输时调用flush()。
作用:请求通过此ChannelOutboundInvoker刷新所有挂起的消息。
作用:请求从Channel读取数据到第一个入站缓冲区,如果读取数据,则触发ChannelInboundHandler#channelRead(ChannelHandlerContext, Object)事件,并触发ChannelInboundHandler#channelReadComplete(ChannelHandlerContext) channelReadComplete事件,以便处理程序可以决定继续读取。如果已经有一个挂起的读操作,这个方法什么也不做。
作用:请求断开与远程对等点的连接,并在操作完成后通知ChannelFuture,原因可能是操作成功,也可能是错误,调用ChannelOutboundHandler的disconnect
作用:请求关闭Channel,并在操作完成后通知ChannelFuture,原因可能是操作成功,也可能是错误,调用ChannelOutboundHandler的close。关闭后,就不可能再重用它了。
作用:请求从之前分配的EventExecutor取消注册,并在操作完成后通知ChannelFuture,原因可能是操作成功,也可能是错误,调用ChannelOutboundHandler的deregister。
这个图是源码io.netty.channel.ChannelPipeline接口的备注部分提供的。
ChannelPipeline的数据结构是双向链表。
Outbound事件最后都是通过HeadContext完成(HeadContext最后调用NioSocketChannelUnsafe响应的方法完成),Inbound事件是从HeadContext开始。
一个处理字节和消息的特殊的捕获全部事件的处理程序,Outbound事件是从tailContext开始,Inbound事件是在tailContext结束。
在Channel中调用DefaultChannelPipeline.fireChannelActive,接下来在Channel交给自己的DefaultChannelPipeline执行了,因为是Inbound事件,所以从HeadContext->TailContext。DefaultChannelPipeline中Inbound事件传递过程:
Context.fireChannelActive -> Connect.findContextInbound -> Connect.invokeChannelActive(final AbstractChannelHandlerContext next)-> next.invokeChannelActive -> nextHandler.channelActive -> nextContext.fireChannelActive
以 Bootstrap.connect 的事件流为例,大致如下:
Bootstrap.connect -> Bootstrap.doResolveAndConnect-> Bootstrap.doResolveAndConnect0-> Bootstrap.doConnect-> AbstractChannel.connect->DefaultChannelPipeline.connect->NioSocketChannelUnsafe.connect->NioSocketChannel.doConnect->SocketChannel.connect
最后都是到了Channel,然后Channel交给自己的DefaultChannelPipeline执行,因为是 Outbound 事件,所以从TailContext ->HeadContext,HeadContext最后调用NioSocketChannelUnsafe响应的方法完成,事件流的NioSocketChannelUnsafe.connect->NioSocketChannel.doConnect->SocketChannel.connect部分就是在HeadContext里面执行的。
Context.connect -> Context.findContextOutbound -> next.invokeConnect -> handler.connect -> Context.connect
一致循环从TailContext 将事件传递到HeadContext。
作者:静夜明灯
链接:https://www.jianshu.com/p/7de2ae969daa