上一篇我们拿到所有的accept到的channel之后,我们回头看事件通知
还记得io.netty.bootstrap.ServerBootstrap#init服务端启动的时候,
ch.eventLoop().execute(new Runnable() {
@Override
public void run() {
//pipline会默认添加一个acceptor,是设置给ServerBootStrap的
//ServerBootstrapAcceptor 专门处理新连接accept进来的处理
pipeline.addLast(new ServerBootstrapAcceptor(
ch, currentChildGroup, currentChildHandler, currentChildOptions, currentChildAttrs));
}
});
这里会给channel添加一个ServerBootstrapAcceptor,先不管这个accept,他是一个InBound类型,接着上面我们来看事件通知pipeline.fireChannelRead(readBuf.get(i));
/**
* 有数据读入的时候会调用(InBound) 也可以手动调用
* @param msg 客户端连接的channel
* @return
*/
@Override
public final ChannelPipeline fireChannelRead(Object msg) {
//pipline节点类的静态方法 穿进去的head
AbstractChannelHandlerContext.invokeChannelRead(head, msg);
return this;
}
AbstractChannelHandlerContext是pipline的一个链表节点,里面维护一个InBound或者OutBound 的adapter
/**
* 静态方法
* @param next 第一次调用next是head 之后依次链表往下找
* @param msg 客户端连接的channel
*/
static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) {
final Object m = next.pipeline.touch(ObjectUtil.checkNotNull(msg, "msg"), next);
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
//调用pipline节点的方法
next.invokeChannelRead(m);
} else {
executor.execute(new Runnable() {
@Override
public void run() {
next.invokeChannelRead(m);
}
});
}
}
/**
* @param msg 包含客户端channel的一个对象
*/
private void invokeChannelRead(Object msg) {
if (invokeHandler()) {
try {
//进入到当前的带调用节点 this = head->..ServerBootstrapAcceptor..->tail
//拿到当前节点包装的handler 调用handler的channelRead
//第一次走的是HeadContext
((ChannelInboundHandler) handler()).channelRead(this, msg);
} catch (Throwable t) {
notifyHandlerException(t);
}
} else {
fireChannelRead(msg);
}
}
这里先走HeadContext节点,然后再走ServerBootstrapAcceptor.channelRead方法,那么我们可以断定,客户端新连接的注册就在这个方法完成的
io.netty.bootstrap.ServerBootstrap.ServerBootstrapAcceptor#channelRead
public void channelRead(ChannelHandlerContext ctx, Object msg) {
//msg 新连接进来会传播事件 传递进来的channel对象
final Channel child = (Channel) msg;
//取出来新连接的pipLine 把Server端配置的handler添加进去
child.pipeline().addLast(childHandler);
setChannelOptions(child, childOptions, logger);
for (Entry, Object> e: childAttrs) {
child.attr((AttributeKey
io.netty.channel.MultithreadEventLoopGroup#register(io.netty.channel.Channel)
@Override
public ChannelFuture register(Channel channel) {
return next().register(channel);
}
这里需要解释一下,NioEventLoopGroup.next()会调用线程选择器chooser,来选择一个NioEventLoop对象完成channel的注册
io.netty.channel.SingleThreadEventLoop#register(io.netty.channel.Channel)
/**
* 注册channel
* @param channel
* @return
*/
@Override
public ChannelFuture register(Channel channel) {
return register(new DefaultChannelPromise(channel, this));
}
@Override
public ChannelFuture register(final ChannelPromise promise) {
ObjectUtil.checkNotNull(promise, "promise");
//转交给unsafe来进行注册
promise.channel().unsafe().register(this, promise);
return promise;
}
io.netty.channel.AbstractChannel.AbstractUnsafe#register
/**
* 注册channel到selector
* @param eventLoop
* @param promise
*/
@Override
public final void register(EventLoop eventLoop, final ChannelPromise promise) {
.....
//保存事件处理线程
AbstractChannel.this.eventLoop = eventLoop;
/**
* 在工作线程知己进行注册
*/
if (eventLoop.inEventLoop()) {
//注册channel
register0(promise);
} else {
try {
//否则执行task任务 添加到队列 异步进行调度
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
} catch (Throwable t) {
....
}
}
io.netty.channel.AbstractChannel.AbstractUnsafe#register0
private void register0(ChannelPromise promise) {
try {
if (!promise.setUncancellable() || !ensureOpen(promise)) {
return;
}
boolean firstRegistration = neverRegistered;
//执行注册channel的逻辑
doRegister();
neverRegistered = false;
registered = true;
//通知pipline添加操作
pipeline.invokeHandlerAddedIfNeeded();
safeSetSuccess(promise);
//通知pipline registe事件
pipeline.fireChannelRegistered();
if (isActive()) {
if (firstRegistration) {
//通知pipline的active事件 header->tail active
pipeline.fireChannelActive();
} else if (config().isAutoRead()) {
// This channel was registered before and autoRead() is set. This means we need to begin read
// again so that we process inbound data.
//
// See https://github.com/netty/netty/issues/4805
beginRead();
}
}
} catch (Throwable t) {
// Close the channel directly to avoid FD leak.
closeForcibly();
closeFuture.setClosed();
safeSetFailure(promise, t);
}
}
先看io.netty.channel.AbstractChannel#doRegister方法,这个是执行注册的方法
@Override
protected void doRegister() throws Exception {
boolean selected = false;
for (;;) {
try {
//注册java的nio channel到selector ops=0表示不关心任何事件,
//只是注册进去 att=this 添加attachments = netty的niochannel
selectionKey = javaChannel().register(eventLoop().unwrappedSelector(), 0, this);
return;
可以看到是调用java原生的channel来注册到NioEventLoop中的selector中去,并且设置attachment是channel(所有selectKey.attachment()拿到的就是channel本身),注册关心事件0,标识不关心任何事件
接着看注册完了之后的通知事件io.netty.channel.Channel#isActive
/**
* 判断channel是否是激活的
* 对于客户端channel来说,channel是打开并且是连接状态的
* @return
*/
@Override
public boolean isActive() {
SocketChannel ch = javaChannel();
return ch.isOpen() && ch.isConnected();
}
之后调用pipeline.fireChannelActive();
@Override
public final ChannelPipeline fireChannelActive() {
AbstractChannelHandlerContext.invokeChannelActive(head);
return this;
}
最终进入HeadContext的channelActive方法
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.fireChannelActive();
//注册read关心事件
readIfIsAutoRead();
}
private void readIfIsAutoRead() {
if (channel.config().isAutoRead()) {
channel.read();
}
}
io.netty.channel.AbstractChannel#read
@Override
public Channel read() {
pipeline.read();
return this;
}
又调用pipline的read方法,继续跟进
@Override
public final ChannelPipeline read() {
tail.read();
return this;
}
调用TailContext的read方法
@Override
public ChannelHandlerContext read() {
final AbstractChannelHandlerContext next = findContextOutbound();
EventExecutor executor = next.executor();
if (executor.inEventLoop()) {
//调用invokeRead方法
next.invokeRead();
} else {
Runnable task = next.invokeReadTask;
if (task == null) {
next.invokeReadTask = task = new Runnable() {
@Override
public void run() {
next.invokeRead();
}
};
}
executor.execute(task);
}
return this;
}
findContextOutbound()会从tail开始往前找到HeadContext
private void invokeRead() {
if (invokeHandler()) {
try {
((ChannelOutboundHandler) handler()).read(this);
} catch (Throwable t) {
notifyHandlerException(t);
}
} else {
read();
}
}
最终进入headContext的read方法
@Override
public void read(ChannelHandlerContext ctx) {
unsafe.beginRead();
}
io.netty.channel.AbstractChannel.AbstractUnsafe#beginRead
@Override
public final void beginRead() {
assertEventLoop();
if (!isActive()) {
return;
}
try {
//真正开始read 注册关心事件
doBeginRead();
} catch (final Exception e) {
invokeLater(new Runnable() {
@Override
public void run() {
pipeline.fireExceptionCaught(e);
}
});
close(voidPromise());
}
}
io.netty.channel.nio.AbstractNioChannel#doBeginRead
@Override
protected void doBeginRead() throws Exception {
// Channel.read() or ChannelHandlerContext.read() was called
final SelectionKey selectionKey = this.selectionKey;
if (!selectionKey.isValid()) {
return;
}
readPending = true;
//取出来构造参数传进来的ops readInterestOp就是构造传进来
final int interestOps = selectionKey.interestOps();
if ((interestOps & readInterestOp) == 0) {
//注册感兴趣事件
selectionKey.interestOps(interestOps | readInterestOp);
}
}
对于这个感兴趣的事件,是channel对象在构造时候传进去的AbstractNioByteChannel(客户端channel)
protected AbstractNioByteChannel(Channel parent, SelectableChannel ch) {
//关心read事件
super(parent, ch, SelectionKey.OP_READ);
}