privatefinalclassNioSocketChannelUnsafeextendsNioByteUnsafe{
@OverrideprotectedExecutor prepareToClose() {
try {
if (javaChannel().isOpen() && config().getSoLinger() > 0) {
// We need to cancel this key of the channel so we may not end up in a eventloop spin// because we try to read or write until the actual close happens which may be later due// SO_LINGER handling.// See https://github.com/netty/netty/issues/4449
doDeregister();
returnGlobalEventExecutor.INSTANCE;
}
} catch (Throwable ignore) {
// Ignore the error as the underlying channel may be closed in the meantime and so// getSoLinger() may produce an exception. In this case we just return null.// See https://github.com/netty/netty/issues/4449
}
returnnull;
}
}
protected class NioByteUnsafe extends AbstractNioUnsafe {
...
@Override
public final void read() {
final ChannelConfig config = config();
if (shouldBreakReadReady(config)) {
clearReadPending();
return;
}
final ChannelPipeline pipeline = pipeline();
// 获取ByteBuf的内存分配器,其实底层还是nio的ByteBuffer
final ByteBufAllocator allocator = config.getAllocator();
// RecvByteBufAllocator处理输入字节数过大和过小的情况,拆包?数据过大的处理?
final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle();
allocHandle.reset(config);
ByteBuf byteBuf = null;
boolean close = false;
try {
do {
// 创建ByteBuf,详见ByteBuf分析
byteBuf = allocHandle.allocate(allocator);
// doReadBytes是将Socket的字节数据读取到byteBuf中// 设置上次读取的字节数,为下次读取数据时分配字节数提供参考
allocHandle.lastBytesRead(doReadBytes(byteBuf));
if (allocHandle.lastBytesRead() <= 0) {
// nothing was read. release the buffer.
byteBuf.release();
byteBuf = null;
close = allocHandle.lastBytesRead() < 0;
if (close) {
// There is nothing left to read as we received an EOF.
readPending = false;
}
break;
}
allocHandle.incMessagesRead(1);
readPending = false;
pipeline.fireChannelRead(byteBuf);
byteBuf = null;
// continueReading用来判断socket数据是否已经读完,是根据ByteBuf可读字节数和本次读取的字节数来判断
} while (allocHandle.continueReading());
// 计算下一次分配的ByteBuf的空间大小
allocHandle.readComplete();
pipeline.fireChannelReadComplete();
if (close) {
closeOnRead(pipeline);
}
} catch (Throwable t) {
handleReadException(pipeline, byteBuf, t, close, allocHandle);
} 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();
}
}
}
}