register操作
register操作之后伴随着多个回调及listener的触发:
【Netty启动流程剖析】// AbstractChannel$AbstractUnsafeprivate void register0(ChannelPromise promise) { boolean firstRegistration = neverRegistered; // 这里调用的是AbstractNioChannel.doRegister // 这里将channel注册上去,并没有关注对应的事件(read/write事件) doRegister(); neverRegistered = false; registered = true;// 调用handlerAdd事件,这里就会调用initChannel方法,设置channel.pipeline,也就是添加 ServerBootstrapAcceptor pipeline.invokeHandlerAddedIfNeeded();// 调用operationComplete回调 safeSetSuccess(promise); // 回调fireChannelRegistered pipeline.fireChannelRegistered(); // Only fire a channelActive if the channel has never been registered. This prevents firing // multiple channel actives if the channel is deregistered and re-registered. if (isActive()) { if (firstRegistration) { // 回调fireChannelActive pipeline.fireChannelActive(); } else if (config().isAutoRead()) { beginRead(); } }}上面代码中的initChannel回调也就是设置对外监听channel的channelHanlder为ServerBootstrapAcceptor;operationComplete回调也就是触发ChannelFutureListener.operationComplete,这里会进行后续的doBind操作 。
// AbstractBootstrapprivate static void doBind0( final ChannelFuture regFuture, final Channel channel, final SocketAddress localAddress, final ChannelPromise promise) { // doBind0向EventLoop任务队列中添加一个bind任务来完成后续操作 。channel.eventLoop().execute(new Runnable() { @Override public void run() { if (regFuture.isSuccess()) { // bind操作 channel.bind(localAddress, promise).addListener(ChannelFutureListener.CLOSE_ON_FAILURE); } } });}bind操作
在回顾上面的bind操作代码,bind操作是在register之后进行的,因为register0是由NioEventLoop执行的,所以main线程需要先判断下future是否完成,如果完成直接进行doBind即可,否则添加listener回调进行doBind 。
文章插图
bind操作及后续初始化操作(channelActive回调、设置监听事件)
public final void bind(final SocketAddress localAddress, final ChannelPromise promise) { boolean wasActive = isActive(); try { // 调用底层bind操作 doBind(localAddress); } catch (Throwable t) { safeSetFailure(promise, t); closeIfClosed(); return; } if (!wasActive && isActive()) { invokeLater(new Runnable() { @Override public void run() { pipeline.fireChannelActive(); } }); } safeSetSuccess(promise);}// 最后底层bind逻辑bind入参包括了backlog,也就是底层会进行listen操作// DefaultChannelPipeline.headContext -> NioMessageUnsafe -> NioServerSocketChannelprotected void doBind(SocketAddress localAddress) throws Exception { if (PlatformDependent.javaVersion() >= 7) { javaChannel().bind(localAddress, config.getBacklog()); } else { javaChannel().socket().bind(localAddress, config.getBacklog()); }}public void channelActive(ChannelHandlerContext ctx) throws Exception { // 回调fireChannelActive ctx.fireChannelActive();// 设置selectKey监听事件,对于监听端口就是SelectionKey.OP_ACCEPT,对于新建连接就是SelectionKey.OP_READ readIfIsAutoRead();}到这里为止整个netty启动流程就基本接近尾声,可以对外提供服务了 。
推荐阅读
- 如何开淘宝店步骤开淘宝网店 淘宝店铺怎么开店流程
- 壁挂炉冻了还能启动吗,壁挂炉冻了怎么解冻
- 怎么把淘宝店转让 接别人转让的店铺流程
- 开水果店的流程 淘宝水果店怎么开
- 淘宝个人店铺过户流程 淘宝店铺过户需要什么条件
- 十大紫砂茗壶展评启动
- 晋中,重走晋商茶路活动启动
- 淘宝商家认证流程 淘宝企业店铺认证流程
- Java JVM启动参数大全
- 跨境电商物流操作流程 货代操作流程