Netty源码解析之ServerSocketChannel close流程

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/heroqiang/article/details/82753614

阅读须知

  • Netty版本:4.1.14.Final
  • 文章中使用/* */注释的方法会做深入分析

正文

本篇文章我们来分析ServerSocketChannel的close流程,这是一个通用的流程,很多地方关闭ServerSocketChannel时都是复用这个流程。
AbstractChannel.AbstractUnsafe:

protected final void closeIfClosed() {
    if (isOpen()) {
        return;
    }
    close(voidPromise());
}

AbstractChannel.AbstractUnsafe:

public final void close(final ChannelPromise promise) {
    assertEventLoop();
    close(promise, CLOSE_CLOSED_CHANNEL_EXCEPTION, CLOSE_CLOSED_CHANNEL_EXCEPTION, false);
}

AbstractChannel.AbstractUnsafe:

private void close(final ChannelPromise promise, final Throwable cause,
   final ClosedChannelException closeCause, final boolean notify) {
	// 设置promise不能被取消
    if (!promise.setUncancellable()) {
        return;
    }
    final ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
    if (outboundBuffer == null) {
        if (!(promise instanceof VoidChannelPromise)) {
	        // 这意味着之前调用了close(),所以我们只注册一个监听器并返回
            closeFuture.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    promise.setSuccess();
                }
            });
        }
        return;
    }
    if (closeFuture.isDone()) {
	    // 已经关闭,将指定的promise标记为成功
        safeSetSuccess(promise);
        return;
    }
    final boolean wasActive = isActive();
    // 不允许向outboundBuffer添加任何消息和刷新操作
    this.outboundBuffer = null;
    // 准备关闭Channel。如果此方法返回Executor,则调用者必须调用Executor的execute方法
    // 并在返回的Executor上调用doClose()。如果此方法返回null,则必须从调用方线程调用doClose()
    Executor closeExecutor = prepareToClose();
    if (closeExecutor != null) {
        closeExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    doClose0(promise); /* 执行close */
                } finally {
                    invokeLater(new Runnable() {
                        @Override
                        public void run() {
	                        // 将所有排队的消息置失败
                            outboundBuffer.failFlushed(cause, notify);
                            // 关闭buffer,释放缓冲区资源
                            outboundBuffer.close(closeCause);
                            /* Channel停用并注销 */
                            fireChannelInactiveAndDeregister(wasActive);
                        }
                    });
                }
            }
        });
    } else {
        try {
            doClose0(promise);
        } finally {
            outboundBuffer.failFlushed(cause, notify);
            outboundBuffer.close(closeCause);
        }
        if (inFlush0) {
            invokeLater(new Runnable() {
                @Override
                public void run() {
                    fireChannelInactiveAndDeregister(wasActive);
                }
            });
        } else {
            fireChannelInactiveAndDeregister(wasActive);
        }
    }
}

AbstractChannel.AbstractUnsafe:

private void doClose0(ChannelPromise promise) {
    try {
        doClose();
        closeFuture.setClosed();
        safeSetSuccess(promise);
    } catch (Throwable t) {
        closeFuture.setClosed();
        safeSetFailure(promise, t);
    }
}

NioServerSocketChannel:

protected void doClose() throws Exception {
    javaChannel().close(); // JDK原生close方法
}

AbstractChannel.AbstractUnsafe:

private void fireChannelInactiveAndDeregister(final boolean wasActive) {
    deregister(voidPromise(), wasActive && !isActive());
}

AbstractChannel.AbstractUnsafe:

private void deregister(final ChannelPromise promise, final boolean fireChannelInactive) {
    if (!promise.setUncancellable()) {
        return;
    }
    if (!registered) {
        safeSetSuccess(promise);
        return;
    }
    invokeLater(new Runnable() {
        @Override
        public void run() {
            try {
	            /* 将Channel从它的EventLoop中注销,默认空实现,子类覆盖 */
                doDeregister();
            } catch (Throwable t) {
                logger.warn("Unexpected exception occurred while deregistering a channel.", t);
            } finally {
                if (fireChannelInactive) {
	                // Channel停用,调用ChannelInboundHandler的channelInactive方法
                    pipeline.fireChannelInactive();
                }
                if (registered) {
                    registered = false;
                    // Channel注销,调用ChannelInboundHandler的channelUnregistered方法
                    pipeline.fireChannelUnregistered();
                }
                safeSetSuccess(promise);
            }
        }
    });
}

AbstractNioChannel:

protected void doDeregister() throws Exception {
    eventLoop().cancel(selectionKey()); // 取消SelectionKey
}

这里的SelectionKey同样来自于JDK的NIO。到这里close流程的源码分析就完成了。

猜你喜欢

转载自blog.csdn.net/heroqiang/article/details/82753614