netty服务端启动channel逻辑

netty 服务端启动

创建服务端 Channel: newChannel()
初始化服务端 Channel: init()
注册 selector: register()
端口绑定: doBind()

创建服务端 channel

bind()
    initAndRegister() 初始化并注册 channel
        newChannel() 创建服务端 channel, 会调用 NioServerSocketChannel 的构造方法
        会调用到 NioServerSocketChannel 的构造方法
        newSocket() 通过 jdk 来创建底层 jdk channel
        NioServerSocketChannelConfig() 设置 tcp 参数
        AbstractNioChannel()
            configureBlocking(false) 设置非阻塞模式
            AbstractChannel(客户端 channel 和 服务端 channel 共用的父类) 创建 id,unsafe(用于 channel 底层操作),pipeline

AbstractChannel 构造方法

protected AbstractChannel(Channel parent) {
    this.parent = parent;
    id = newId(); // 给每个 channel 分配一个唯一 id
    unsafe = newUnsafe(); // 每个 channel 内部需要一个 Unsafe 的实例, 封装了对 Java 底层 Socket 的操作
    pipeline = newChannelPipeline(); // 每个 channel 内部都会创建一个 pipeline
}

AbstractNioChannel 构造方法

protected AbstractNioChannel(Channel parent, SelectableChannel ch, int readInterestOp) {
    // ...
    this.readInterestOp = readInterestOp; // 保存 SelectionKey.OP_READ 信息
    try {
        ch.configureBlocking(false); // 设置 channel 的非阻塞模式
    } catch (IOException e) {
        // ...
    }
}

NioServerSocketChannel 构造方法

public NioServerSocketChannel(ServerSocketChannel channel) {
    super(null, channel, SelectionKey.OP_ACCEPT); // 对于服务端来说, 关心的是 SelectionKey.OP_ACCEPT 事件, 等待客户端连接
    config = new NioServerSocketChannelConfig(this, javaChannel().socket()); // serverSocketChannel 的配置
}

初始化服务端 Channel

bind() 入口
    initAndRegister() 初始化并注册
        newChannel() 创建服务端 channel
        init() 初始化服务端 channel
            设置 ChannelOptions 和 ChannelAttrs
            设置 ChildOptions 和 ChildAttrs
            将自定义的 handler 设置到 pipeline
            添加 ServerBootstrapAcceptor 到 pipeline

注册 selector

bind() 入口
    initAndRegister() 初始化并注册
        newChannel() 1. 创建服务端 channel
        init() 2. 初始化服务端 channel
        config().group().register(channel) 3. 注册 selector. 将初始化过的 NioServerSocketChannel 注册到配置的 EventLoopGroup 对象上, 返回 ChannelFuture 对象
            this.eventLoop = eventLoop 绑定线程
            resgiter0() 实际注册
                doRegister() 调用 jdk 底层注册
                invokeHandlerAddedIfNeeded()
register:465, AbstractChannel$AbstractUnsafe (io.netty.channel)
register:80, SingleThreadEventLoop (io.netty.channel)
register:74, SingleThreadEventLoop (io.netty.channel)
register:86, MultithreadEventLoopGroup (io.netty.channel)
initAndRegister:333, AbstractBootstrap (io.netty.bootstrap)
doBind:282, AbstractBootstrap (io.netty.bootstrap)
bind:278, AbstractBootstrap (io.netty.bootstrap)
bind:253, AbstractBootstrap (io.netty.bootstrap)
run:52, TimeServer (com.zc.netty.action.demo.time)
main:31, TimeServer (com.zc.netty.action.demo.time)

io.netty.channel.nio.AbstractNioChannel#doRegister

protected void doRegister() throws Exception {
    boolean selected = false;
    for (;;) {
        try { // register(selector, 0表示不关心任何事件, attachment将this绑定到selector上)
            selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this); // 调用jdk底层channel注册,将channel注册到selector上
            return;
        } catch (CancelledKeyException e) {
            if (!selected) {
                // Force the Selector to select now as the "canceled" SelectionKey may still be
                // cached and not removed because no Select.select(..) operation was called yet.
                eventLoop().selectNow();
                selected = true;
            } else {
                // We forced a select operation on the selector before but the SelectionKey is still cached
                // for whatever reason. JDK bug ?
                throw e;
            }
        }
    }
}

端口绑定

AbstractUnsafe.bind()
    initAndRegister() 初始化并注册
    doBind() 绑定逻辑
        javaChannel().bind() jdk 底层绑定
    pipeline.fireChannelActive() 触发事件

io.netty.channel.socket.nio.NioServerSocketChannel#doBind

protected void doBind(SocketAddress localAddress) throws Exception {
    if (PlatformDependent.javaVersion() >= 7) {
        javaChannel().bind(localAddress, config.getBacklog()); // 调用jdk底层的 bind()
    } else {
        javaChannel().socket().bind(localAddress, config.getBacklog());
    }
}
doBind:129, NioServerSocketChannel (io.netty.channel.socket.nio)
bind:563, AbstractChannel$AbstractUnsafe (io.netty.channel)
bind:1332, DefaultChannelPipeline$HeadContext (io.netty.channel)
invokeBind:488, AbstractChannelHandlerContext (io.netty.channel)
bind:473, AbstractChannelHandlerContext (io.netty.channel)
bind:984, DefaultChannelPipeline (io.netty.channel)
bind:259, AbstractChannel (io.netty.channel)
run:366, AbstractBootstrap$2 (io.netty.bootstrap)
safeExecute$$$capture:163, AbstractEventExecutor (io.netty.util.concurrent)
safeExecute:-1, AbstractEventExecutor (io.netty.util.concurrent)
 - Async stack trace
addTask:-1, SingleThreadEventExecutor (io.netty.util.concurrent)
execute:756, SingleThreadEventExecutor (io.netty.util.concurrent)
doBind0:362, AbstractBootstrap (io.netty.bootstrap)
access$000:50, AbstractBootstrap (io.netty.bootstrap)
operationComplete:309, AbstractBootstrap$1 (io.netty.bootstrap)
operationComplete:296, AbstractBootstrap$1 (io.netty.bootstrap)
notifyListener0:502, DefaultPromise (io.netty.util.concurrent)
notifyListenersNow:476, DefaultPromise (io.netty.util.concurrent)
notifyListeners:415, DefaultPromise (io.netty.util.concurrent)
setValue0:540, DefaultPromise (io.netty.util.concurrent)
setSuccess0:529, DefaultPromise (io.netty.util.concurrent)
trySuccess:101, DefaultPromise (io.netty.util.concurrent)
trySuccess:84, DefaultChannelPromise (io.netty.channel)
safeSetSuccess:1009, AbstractChannel$AbstractUnsafe (io.netty.channel)
register0:517, AbstractChannel$AbstractUnsafe (io.netty.channel)
access$200:428, AbstractChannel$AbstractUnsafe (io.netty.channel)
run:487, AbstractChannel$AbstractUnsafe$1 (io.netty.channel)
safeExecute$$$capture:163, AbstractEventExecutor (io.netty.util.concurrent)
safeExecute:-1, AbstractEventExecutor (io.netty.util.concurrent)
 - Async stack trace
addTask:-1, SingleThreadEventExecutor (io.netty.util.concurrent)
execute:756, SingleThreadEventExecutor (io.netty.util.concurrent)
register:484, AbstractChannel$AbstractUnsafe (io.netty.channel)
register:80, SingleThreadEventLoop (io.netty.channel)
register:74, SingleThreadEventLoop (io.netty.channel)
register:86, MultithreadEventLoopGroup (io.netty.channel)
initAndRegister:333, AbstractBootstrap (io.netty.bootstrap)
doBind:282, AbstractBootstrap (io.netty.bootstrap)
bind:278, AbstractBootstrap (io.netty.bootstrap)
bind:253, AbstractBootstrap (io.netty.bootstrap)
run:52, TimeServer (com.zc.netty.action.demo.time)
main:31, TimeServer (com.zc.netty.action.demo.time)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FlyingZCC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值