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)