版权声明:本文为博主原创文章,转载请注明出处。 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流程的源码分析就完成了。