Netty-Channel注册源码分析

Jewel ·
更新时间:2024-11-14
· 670 次阅读

Channel注册分为ServerSocketChannel和SockerChannel注册,服务端启动的时候会先进行ServerSocketChannel的注册,启动完成后,每当有一个客户端连接过来,会进行一次SocketChannel注册。

ServerSocketChannel注册

在这里插入图片描述
在完成channel的创建以及初始化之后,接下来进行channel的注册过程。

先看下config():
在这里插入图片描述
在这里插入图片描述
config是ServerBootstrap的成员变量实例ServerBootstrapConfig。ServerBootstrap在前面的准备工作完成了一系列的赋值操作。

group():
在这里插入图片描述
进入到了ServerBootstrapConfig的父类AbstractBootstrapConfig的group()方法,继续往下执行:
在这里插入图片描述
这个group,就是serverBootstrap.group(bossGroup,workerGroup)传进来的bossGroup。

register(channel):
在这里插入图片描述
进入到了NioEventLoopGroup的父类MultithreadEventLoopGroup的register(channel)方法,next()跟进去后,最终来到了MultithreadEventLoopGroup的父类MultithreadEventExecutorGroup的next()方法:
在这里插入图片描述
这边会返回一个EventExecutor,实际返回的是一个NioEventLoop实例(EventLoop是EventExecutor的子类)。关于选择器chooser的创建及初始化详见服务端初始化过程(待补充)。
在回到MultithreadEventLoopGroup的register(channel)方法,跟进去:
在这里插入图片描述
来到了NioEventLoop的父类SIngleThreadEventLoop的register(channel)方法,再跟进去:
在这里插入图片描述
进入到promise.channel().unsafe().register(this, promise)的register(this, promise)中:
在这里插入图片描述
跟进run()方法中的register0(promise):
在这里插入图片描述
跟进doRegister():
在这里插入图片描述
回到register0(promise)方法往下执行,将registered设为true,跟进pipeline.invokeHandlerAddedIfNeeded():
在这里插入图片描述
跟进callHandlerAddedForAllHandlers()方法:
在这里插入图片描述
在这里插入图片描述
再回到register0(promise)方法往下执行
在这里插入图片描述
跟进pipeline.fireChannelRegistered():
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
跟进channelRegistered(this):
在这里插入图片描述
跟进ctx.fireChannelRegistered():
在这里插入图片描述
在这里插入图片描述
在这边ServerSocketChannel对应的pipeline中,HeadContext的下一个入站context对象直接是TailContext。
继续跟进:
在这里插入图片描述
在这里插入图片描述
这里为什么是空的?因为TailContext已经是pipeline的最后一站了,所以不需要继续往后面传递。

SocketChannel注册

参见ServerBootstrapAcceptor源码分析,流程进入到MultithreadEventLoopGroup的register(channel)方法:
在这里插入图片描述
从workerGroup拿到一个NioEventLoop后进行register(channel):
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
NioSocketChannel的interest set 为什么也是0呢?不着急,先往下看。

回到register0(promise):
在这里插入图片描述
跟进pipeline.fireChannelRegistered():
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
本来应该执行LengthFieldBasedFrameDecoder这个handler的channelRegistered(ctx)方法,所以在这里实现了用户自定义handler的channelRegistered(ctx)方法的调用,但是因为LengthFieldBasedFrameDecoder没有重写,所以进入了父类方法:
在这里插入图片描述
在这里插入图片描述
又到了前面重复的流程,直到pipeline的最后一站TailContext。
至此完成pipeline.fireChannelRegistered()。

继续往下执行
在这里插入图片描述
跟进pipeline.fireChannelActive()看一看:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
到目前为止,和pipeline.fireChannelRegister()没什么不一样,重点看readIfIsAutoRead()方法,跟进去:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
发现来到了handler的read(ctx)方法,如果子类没有重写这个方法,则调用父类ChannelOutboundHandlerAdapter的read(ctx)方法。
在这里插入图片描述
会重复上面的流程,直到pipeline中最前面的那个出站context,就是HeadContext实例,直接到HeadContex看一下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
终于,我们发现NioSocketChannel的interest set由0设为了1。


作者:suxm&



netty 源码

需要 登录 后方可回复, 如果你还没有账号请 注册新账号