if (exception != null) { closed = closeOnReadError(exception);
pipeline.fireExceptionCaught(exception); }
if (closed) { inputShutdown = true; if (isOpen()) { close(voidPromise()); } } } finally { // Check if there is a readPending which was not processed yet. // This could be for two reasons: // * The user called Channel.read() or ChannelHandlerContext.read() in channelRead(...) method // * The user called Channel.read() or ChannelHandlerContext.read() in channelReadComplete(...) method // // See https://github.com/netty/netty/issues/2254 if (!readPending && !config.isAutoRead()) { removeReadOp(); } } }
// AbstraceUnsafe /** * - NioEventLoop线程执行 Jdk的Channel注册到复用器上 不关注事件(关注的事件是0 因为对于NIO而言 注册复用器是最前置的动作 后续的连接和可读对于ServerSocket而言都是收到了可读事件 所以按照职责分工 让ServerBootstrapAcceptor去更要关注的事件) * - 发布事件 * - 发布handlerAdd事件 触发ChannelInitializer方法执行 * - 发布ChannelRegister事件 * - 根据Channel状态判定事件(服务端bind或者客户端connect的Channel现在都还没有处于active打开状态) * - 服务端Accept出来的NioSocketChannel 初始状态就已经是active打开状态 * - 首次注册到workerGroup的时候发布ChannelActive事件 */ privatevoidregister0(ChannelPromise promise) { try { // check if the channel is still open as it could be closed in the mean time when the register // call was outside of the eventLoop if (!promise.setUncancellable() || !ensureOpen(promise)) return; booleanfirstRegistration= neverRegistered; /** * 实际的注册 * jdk底层操作 将channel注册到selector复用器上 不关注Channel发生的事件类型 * 注册复用器的时候监听集合是空的(也就是让复用器对Jdk的Channel感兴趣的事件是0) */ AbstractChannel.this.doRegister(); neverRegistered = false; AbstractChannel.this.registered = true; // 标识Channel跟NioEventLoop绑定成功
// Ensure we call handlerAdded(...) before we actually notify the promise. This is needed as the // user may already fire events through the pipeline in the ChannelFutureListener.
/** * 发布register事件 * 让pipeline中handler关注channelRegistered(...)的handler执行 */ 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. /** * active指channel已经打开 * - NioServerSocketChannel已经执行过bind操作 * - NioSocketChannel... * * 注册复用器属于前置操作 * - 先于NioServerSocketChannel的bind(bind+listen)操作 * - 先于NioSocketChannel的connect操作 * 因此Channel注册完复用器走到这时Channel还没有active * * 但是如果是NioServerSocketChannel通过accept生成了一个NioSocketChannel在workerGroup中发生了注册复用器时 这时候 */ if (isActive()) { if (firstRegistration) { pipeline.fireChannelActive(); // 服务端accept出来的NioSocketChannel注册到workerGroup中后发布ChannelActive事件 触发HeadHandler将复用器关注的事件增加对可读的关注 0->16 } elseif (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 this.beginRead(); } } } catch (Throwable t) { // Close the channel directly to avoid FD leak. closeForcibly(); closeFuture.setClosed(); safeSetFailure(promise, t); } }