Netty源码分析第一章:Netty启动流程

 

第三节:服务端channel初始化

回顾上一小节的initAndRegister()方法:

final ChannelFuture initAndRegister() {
Channel channel = null;
try {
//创建channel
channel = channelFactory.newChannel();
//初始化channel
init(channel);
} catch (Throwable t) {
//忽略非关键代码
}
ChannelFuture regFuture = config().group().register(channel);
//忽略非关键代码
return regFuture;
}

简单回顾上一小节内容, 我们跟完了创建channel的步骤, 知道了Netty的NioServerSocketChannel和jdk的ServerSocketChannel之间的关系, NioServerSocketChannel和jdk的channel是组合关系, 在其父类AbstractChannel中有jdk的channel的一个成员变量, 通过创建netty的channel为jdk的channel赋值

我们继续往下看init(Channel)方法

因为是ServerBootstrap对象调用的init()方法, 所以我们跟到ServerBootstrap类的init()方法中:

void init(Channel channel) throws Exception {
//获取用户定义的选项(1)
final Map<ChannelOption<?>, Object> options = options0();
synchronized (options) {
channel.config().setOptions(options);
} //获取用户定义的属性(2)
final Map<AttributeKey<?>, Object> attrs = attrs0();
synchronized (attrs) {
for (Entry<AttributeKey<?>, Object> e: attrs.entrySet()) {
@SuppressWarnings("unchecked")
AttributeKey<Object> key = (AttributeKey<Object>) e.getKey();
channel.attr(key).set(e.getValue());
}
}
//获取channel的pipline(3)
ChannelPipeline p = channel.pipeline();
//work线程组(4)
final EventLoopGroup currentChildGroup = childGroup;
//用户设置的Handler(5)
final ChannelHandler currentChildHandler = childHandler;
final Entry<ChannelOption<?>, Object>[] currentChildOptions;
final Entry<AttributeKey<?>, Object>[] currentChildAttrs;
//选项转化为Entry对象(6)
synchronized (childOptions) {
currentChildOptions = childOptions.entrySet().toArray(newOptionArray(childOptions.size()));
}
//属性转化为Entry对象(7)
synchronized (childAttrs) {
currentChildAttrs = childAttrs.entrySet().toArray(newAttrArray(childAttrs.size()));
}
//添加服务端handler(8)
p.addLast(new ChannelInitializer<Channel>() {
//初始化channel
@Override
public void initChannel(Channel ch) throws Exception {
final ChannelPipeline pipeline = ch.pipeline();
ChannelHandler handler = config.handler();
if (handler != null) {
pipeline.addLast(handler);
}
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
pipeline.addLast(new ServerBootstrapAcceptor(
currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
}
});
}

初看起来代码好长, 其实并不复杂, 这里对每一步进行一个简述:

步骤(1), (2)是获取的用户代码中定义的选项和属性

步骤(3)是获取channel的pipeline, 这个channel就是上一小节我们学习创建的NioServerSocketChannel, 我们知道每个channel都有个pipeline的属性, 是AbstractChannel的成员变量, 而这里的pipeline()就是获取其与channel绑定的pipeline, 这个pipline, 会在后面的章节中讲到

步骤(4)是获取worker线程组, 我们知道这个worker线程组就是在用户代码中创建的NioEventLoopGroup, 后来在ServerBootstrap的group()方法中赋值为ServerBootstrap的成员变量, 而这里是获取其成员变量, 并赋值到局部变量currentChildGroup中, NioEventLoop相关知识会在后面的章节讲到

步骤(6), (7)是将选项和属性转化成Entry对象

步骤(8)是添加服务端Handler, 是通过和channel绑定的pipeline调用addLast()方法进行添加, 传入一个ChannelInitializer类的子类对象, 至于addLast方法是做什么的, ChannelInitializer是做什么的, 后绪章节都会给大家详细剖析, 这里不必深究

这一小节我们了解了有关channel初始化的过程, 我们目前只需了解其大概步骤, 有关addLast的逻辑会在后面的章节进行详细剖析

上一节: NioServerSocketChannel的创建

下一节: 注册多路复用

Netty源码分析第1章(Netty启动流程)---->第3节: 服务端channel初始化的更多相关文章

  1. Netty源码分析第3章(客户端接入流程)---->第4节: NioSocketChannel注册到selector

    Netty源码分析第三章: 客户端接入流程 第四节: NioSocketChannel注册到selector 我们回到最初的NioMessageUnsafe的read()方法: public void ...

  2. Netty源码分析第3章(客户端接入流程)---->第5节: 监听读事件

    Netty源码分析第三章: 客户端接入流程 第五节: 监听读事件 我们回到AbstractUnsafe的register0()方法: private void register0(ChannelPro ...

  3. Netty源码分析第3章(客户端接入流程)---->第1节: 初始化NioSockectChannelConfig

    Netty源码分析第三章: 客户端接入流程 概述: 之前的章节学习了server启动以及eventLoop相关的逻辑, eventLoop轮询到客户端接入事件之后是如何处理的?这一章我们循序渐进, 带 ...

  4. Netty源码分析第3章(客户端接入流程)---->第2节: 处理接入事件之handle的创建

    Netty源码分析第三章: 客户端接入流程 第二节: 处理接入事件之handle的创建 上一小节我们剖析完成了与channel绑定的ChannelConfig初始化相关的流程, 这一小节继续剖析客户端 ...

  5. Netty源码分析第3章(客户端接入流程)---->第3节: NioSocketChannel的创建

    Netty源码分析第三章: 客户端接入流程 第三节: NioSocketChannel的创建 回到上一小节的read()方法: public void read() { //必须是NioEventLo ...

  6. Netty源码分析第1章(Netty启动流程)---->第1节: 服务端初始化

    Netty源码分析第一章:  Server启动流程 概述: 本章主要讲解server启动的关键步骤, 读者只需要了解server启动的大概逻辑, 知道关键的步骤在哪个类执行即可, 并不需要了解每一步的 ...

  7. Netty源码分析第1章(Netty启动流程)---->第2节: NioServerSocketChannel的创建

    Netty源码分析第一章:  Server启动流程 第二节:NioServerSocketChannel的创建 我们如果熟悉Nio, 则对channel的概念则不会陌生, channel在相当于一个通 ...

  8. Netty源码分析第1章(Netty启动流程)---->第4节: 注册多路复用

    Netty源码分析第一章:Netty启动流程   第四节:注册多路复用 回顾下以上的小节, 我们知道了channel的的创建和初始化过程, 那么channel是如何注册到selector中的呢?我们继 ...

  9. Netty源码分析第1章(Netty启动流程)---->第5节: 绑定端口

    Netty源码分析第一章:Netty启动步骤 第五节:绑定端口 上一小节我们学习了channel注册在selector的步骤, 仅仅做了注册但并没有监听事件, 事件是如何监听的呢? 我们继续跟第一小节 ...

随机推荐

  1. python第十六课——外部函数and内部函数

    1.外部函数&内部函数 内部函数: 定义在某个函数的内部,就是内部函数: [注意事项]: 1).内部函数可以随意使用它外部函数中的内容 2).外部函数不能使用内部函数中的内容 3).内部函数不 ...

  2. Js 面向对象之封装,继承,原型,原型链

    封装 ,继承 ,原型, 原型链 封装 ? 面向对象有三大特性,封装.继承和多态.对于ES5来说,没有class(类)的概念,并且由于JS的函数级作用域(函数内部的变量在函数外访问不到),所以我们就可以 ...

  3. 集合之List总结

    前面LZ已经充分介绍了有关于List接口的大部分知识,如ArrayList.LinkedList.Vector.Stack,通过这几个知识点可以对List接口有了比较深的了解了.只有通过归纳总结的知识 ...

  4. P1131 [ZJOI2007]时态同步

    题目描述 小Q在电子工艺实习课上学习焊接电路板.一块电路板由若干个元件组成,我们不妨称之为节点,并将其用数字1,2,3….进行标号.电路板的各个节点由若干不相交的导线相连接,且对于电路板的任何两个节点 ...

  5. STM32中用 stop 模式 配合低功耗模式下的自动唤醒(AWU) 能否实现FreeRTOS tickless 模式

    已经实现  ,2018年11月17日11:56:42,具体 如下: 第一步 : 修改 void vPortSetupTimerInterrupt( void ) 函数 ,修改原来的 systick 定 ...

  6. 【git3】git+Gogs+webStorm的使用

    Gogs:相比gitlab更轻量级,基于golang的搭建自助 Git 服务.使用Gogs轻松搭建可能比GitLab更好用的Git服务平台. 参考资料:http://blog.csdn.net/u01 ...

  7. mysql索引和外键

    innodb外键: 1.CASCADE:从父表删除或更新会自动删除或更新子表中匹配的行 2.SET NULL:从父表删除或更新行,会设置子表中的外键列为NULL,但必须保证子表列没有指定NOT NUL ...

  8. linux定时任务-crontab

    使用场景: 有时候线上服务器挂了,或者一些数据推送不正常,一般来说我们需要做的就是将项目重启运行,或者检查核对出问题的位置,来快速解决,很多时候我们不得不登上服务器来查看,这个对于目前工作日益繁忙的我 ...

  9. vue父组件为子组件传值传不过去?vue为数组传值,不能直接用等于的方式,要用循环加push的方式

    父组件为子组件传值不成功,子组件拿不到值,不能直接赋值,要用循环加push的方式赋值.

  10. swoft orm中的坑(针对实体类的属性名称和数据库字段不相等)

    最近在用swoft的orm,发现了一些问题: 首先看下实体类的定义 它的属性名称和所映射的数据库字段名不一致,这个就会导致蛋疼的问题,首先,在我们使用orm的时候,应该使用哪个字段? 我直接说结论,在 ...