Netty-读写原理

归档


读原理

    protected class NioByteUnsafe extends AbstractNioUnsafe {
        @Override
        public final void read() {
            ... // 校验处理
            final ChannelPipeline pipeline = pipeline();
            /**
             * allocator   用于创建 ByteBuf 实例
             *             测试时为 io.netty.buffer.PooledByteBufAllocator 实例
             * allocHandle 用于计算 ByteBuf 大小(初始时的)
             *             测试时为 io.netty.channel.AdaptiveRecvByteBufAllocator.HandleImpl 实例
             */
            final ByteBufAllocator allocator = config.getAllocator();
            final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle(); // sign_m_001 
            allocHandle.reset(config); // 如果是缓存的 allocHandle 则重置下

            ByteBuf byteBuf = null;
            boolean close = false;
            try {
                do {
                    byteBuf = allocHandle.allocate(allocator);          // 分配 ByteBuf
                    allocHandle.lastBytesRead(doReadBytes(byteBuf));    // sign_m_010 读取信道内容
                    if (allocHandle.lastBytesRead() <= 0) {
                        ... // 无数据可读,设置 close 为 true 等处理
                        break;
                    }

                    allocHandle.incMessagesRead(1);
                    pipeline.fireChannelRead(byteBuf);      // sign_o_010 发送读取的字节
                    byteBuf = null;
                } while (allocHandle.continueReading());

                allocHandle.readComplete();
                pipeline.fireChannelReadComplete();         // sign_o_020 发送读取完成事件

                if (close) {
                    closeOnRead(pipeline); // 关闭读
                }
            } ... // catch finally 
        }
    }
  • io.netty.channel.AbstractChannel.AbstractUnsafe
    protected abstract class AbstractUnsafe implements Unsafe {
        private RecvByteBufAllocator.Handle recvHandle;

        // sign_m_001
        @Override
        public RecvByteBufAllocator.Handle recvBufAllocHandle() {
            if (recvHandle == null) {
                recvHandle = config().getRecvByteBufAllocator().newHandle();
            }
            return recvHandle; // 相当于缓存
        }
    }
  • io.netty.channel.socket.nio.NioSocketChannel
public class NioSocketChannel extends AbstractNioByteChannel implements io.netty.channel.socket.SocketChannel {
    // sign_m_010 读取信道内容
    @Override
    protected int doReadBytes(ByteBuf byteBuf) throws Exception {
        final RecvByteBufAllocator.Handle allocHandle = unsafe().recvBufAllocHandle();
        allocHandle.attemptedBytesRead(byteBuf.writableBytes());
        /**
         * byteBuf 为 io.netty.buffer.PooledUnsafeDirectByteBuf 实例
         * sign_m_020 读取 Java 底层信道内容
         */
        return byteBuf.writeBytes(javaChannel(), allocHandle.attemptedBytesRead());
    }
}
  • io.netty.buffer.AbstractByteBuf
public abstract class AbstractByteBuf extends ByteBuf {
    // sign_m_020 读取底层信道内容
    @Override
    public int writeBytes(ScatteringByteChannel in, int length) throws IOException {
        ensureWritable(length);
        int writtenBytes = setBytes(writerIndex, in, length); // sign_m_030 写入内容
        if (writtenBytes > 0) {
            writerIndex += writtenBytes; // 改写索引
        }
        return writtenBytes;
    }
}
  • io.netty.buffer.PooledByteBuf
abstract class PooledByteBuf<T> extends AbstractReferenceCountedByteBuf {
    // sign_m_030 写入内容
    @Override
    public final int setBytes(int index, ScatteringByteChannel in, int length) throws IOException {
        try {
            /**
             * internalNioBuffer(index, length) 返回 ByteBuffer 实例
             * 读取信道内容到 ByteBuffer 缓冲区
             */
            return in.read(internalNioBuffer(index, length));
        } catch (ClosedChannelException ignored) {
            return -1;
        }
    }

    // 返回 ByteBuffer 实例
    @Override
    public final ByteBuffer internalNioBuffer(int index, int length) {
        checkIndex(index, length);
        return _internalNioBuffer(index, length, false);
    }

    // 返回 ByteBuffer 实例
    final ByteBuffer _internalNioBuffer(int index, int length, boolean duplicate) {
        index = idx(index);
        ByteBuffer buffer = duplicate ? newInternalNioBuffer(memory) : internalNioBuffer();
        buffer.limit(index + length).position(index);
        return buffer;
    }

    // 返回内部 ByteBuffer 实例
    protected final ByteBuffer internalNioBuffer() {
        ByteBuffer tmpNioBuf = this.tmpNioBuf;
        if (tmpNioBuf == null) { // 内部 ByteBuffer 实例为空,则创建
            this.tmpNioBuf = tmpNioBuf = newInternalNioBuffer(memory); // sign_m_040 创建 ByteBuffer 实例
        } else {
            tmpNioBuf.clear();
        }
        return tmpNioBuf;
    }
}
  • io.netty.buffer.PooledUnsafeDirectByteBuf
final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
    // sign_m_040 创建 ByteBuffer 实例
    @Override
    protected ByteBuffer newInternalNioBuffer(ByteBuffer memory) {
        /**
         * memory 为 java.nio.DirectByteBuffer 实例
         */
        return memory.duplicate(); // 创建副本
    }
}

写原理

  • 主要有两部分:
    • HeadContext#write() 写入消息到缓冲区
    • HeadContext#flush() 推送消息到对端

写入

    final class HeadContext extends AbstractChannelHandlerContext
                            implements ChannelOutboundHandler, ChannelInboundHandler 
    {
        // sign_o_030 写入消息
        @Override
        public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
            /**
             * msg 为 io.netty.buffer.PooledUnsafeDirectByteBuf 实例
             * unsafe 为 io.netty.channel.socket.nio.NioSocketChannel.NioSocketChannelUnsafe 实例
             * sign_m_100 写入消息到信道
             */
            unsafe.write(msg, promise);
        }
    }
  • io.netty.channel.AbstractChannel.AbstractUnsafe
    protected abstract class AbstractUnsafe implements Unsafe {
        // sign_m_100 写入消息到信道
        @Override
        public final void write(Object msg, ChannelPromise promise) {
            ... // 省略校验

            int size;
            try {
                msg = filterOutboundMessage(msg); // sign_m_110 封装处理
                size = pipeline.estimatorHandle().size(msg);
                if (size < 0) {
                    size = 0;
                }
            } ... // catch
            outboundBuffer.addMessage(msg, size, promise); // 添加要发送的缓冲区
        }
    }
  • io.netty.channel.nio.AbstractNioByteChannel
public abstract class AbstractNioByteChannel extends AbstractNioChannel {
    // sign_m_110 封装处理
    @Override
    protected final Object filterOutboundMessage(Object msg) {
        if (msg instanceof ByteBuf) {
            ByteBuf buf = (ByteBuf) msg;
            if (buf.isDirect()) {
                return msg; // msg 为 PooledUnsafeDirectByteBuf 实例,直接返回
            }
            return newDirectBuffer(buf);
        }
        ... // 省略其他处理
    }
}

推送

  • 参考:简单示例-客户端 sign_u_002

    • 调用点:channel.flush(); // sign_u_002 推送消息
  • io.netty.channel.DefaultChannelPipeline.HeadContext

    • 最终是头节点推送
    final class HeadContext extends AbstractChannelHandlerContext
                            implements ChannelOutboundHandler, ChannelInboundHandler 
    {
        @Override
        public void flush(ChannelHandlerContext ctx) {
            /**
             * unsafe 为 io.netty.channel.socket.nio.NioSocketChannel.NioSocketChannelUnsafe 实例
             * sign_m_120 推送消息
             */
            unsafe.flush();
        }
    }
  • io.netty.channel.AbstractChannel.AbstractUnsafe
    protected abstract class AbstractUnsafe implements Unsafe {
        // sign_m_120 推送消息
        @Override
        public final void flush() {
            ... // 省略校验
            outboundBuffer.addFlush();
            flush0(); // sign_m_121 推送消息
        }

        // sign_m_121 推送消息 (子类 AbstractNioUnsafe 重写,做了校验,但最终还是调用此方法)
        protected void flush0() {
            ... // 省略校验
            try {
                doWrite(outboundBuffer); // sign_m_130 写入信道
            } ... // catch finally 
        }
    }
  • io.netty.channel.socket.nio.NioSocketChannel
public class NioSocketChannel extends AbstractNioByteChannel implements io.netty.channel.socket.SocketChannel {
    // sign_m_130 写入信道
    @Override
    protected void doWrite(ChannelOutboundBuffer in) throws Exception {
        SocketChannel ch = javaChannel();
        int writeSpinCount = config().getWriteSpinCount();
        do {
            ... // 省略校验

            int maxBytesPerGatheringWrite = ((NioSocketChannelConfig) config).getMaxBytesPerGatheringWrite();
            ByteBuffer[] nioBuffers = in.nioBuffers(1024, maxBytesPerGatheringWrite);
            int nioBufferCnt = in.nioBufferCount();

            switch (nioBufferCnt) {
                case 0: ... // 略
                case 1: {
                    ByteBuffer buffer = nioBuffers[0];
                    int attemptedBytes = buffer.remaining();
                    final int localWrittenBytes = ch.write(buffer); // 调用 Java 底层信道写入消息
                    ... // 省略其他
                    in.removeBytes(localWrittenBytes); // 清空已发送的
                    --writeSpinCount;
                    break;
                }
                default: ... // 略
            }
        } while (writeSpinCount > 0);

        ... // 略
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值