Netty消息接受

直接看NioEventloop里面处理读和accept时间都是在NioByteUnsafe里面,所以这时候发过来的有可能是channel也有可能是我们的消息

 public final void read() {
            final ChannelConfig config = config();
            根据输入判断是否应该读取
            if (shouldBreakReadReady(config)) {
            当我们注册channel成功后激活channel的时候会设置readPending=true,现在如果出现异常则设置其为false
                clearReadPending();
                return;
            }
            final ChannelPipeline pipeline = pipeline();
            获取分配内存的分配器
            final ByteBufAllocator allocator = config.getAllocator();
            获取接受消息缓冲的handler
            final RecvByteBufAllocator.Handle allocHandle = recvBufAllocHandle();
            *重置已累积的所有计数器,并建议下一次应读取多少消息/字节
          *读取循环。 这边对于每次接收到的消息进行发送的时候 会有一个统计
            allocHandle.reset(config);

            ByteBuf byteBuf = null;
            boolean close = false;
            try {
                do {
                根据接受缓存区分配的大小通过allocator分配内存去读取数据
                    byteBuf = allocHandle.allocate(allocator);
                    读取字节数,记录下读取多少字节 当读取的字节等于尝是调用的字节我们调用record
                    去调节nextReceiveBufferSize
                    allocHandle.lastBytesRead(doReadBytes(byteBuf));
                    if (allocHandle.lastBytesRead() <= 0) {
                    如果没读取到则释放bytebuf
                        // nothing was read. release the buffer.
                        byteBuf.release();
                        byteBuf = null;
                        上一次的读取小于0 标识我们接收到了EOF 直接设置readpending=false
                        End Of File的缩写,在操作系统中表示资料源无更多的资料可读取
                        close = allocHandle.lastBytesRead() < 0;
                        if (close) {
                            // There is nothing left to read as we received an EOF.
                            readPending = false;
                        }
                        break;
                    }
            totalMessages+1
                    allocHandle.incMessagesRead(1);
                    readPending=true表示还未开始读取 fasle表示已经读了或者读完
                    readPending = false;
                    传递read事件
                    pipeline.fireChannelRead(byteBuf);
                    byteBuf = null;
                    当是自动读取 且(没有获取更多的数据 或者尝试读取的字节等于最后读取的字节)且
    总消息数小于最大每次读取的消息数量且读取的总字节数大于0
                } while (allocHandle.continueReading());
            调用record去调节nextReceiveBufferSize
                allocHandle.readComplete();
                触发事件
                pipeline.fireChannelReadComplete();
当已经读到消息尾部的时候
我们设置关闭标识,然后发送fireUserEventTriggered事件 (即执行用户的事件)
一般情况下如果消息发生频率很高,每次都不会close 。只有在规定执行范围内执行完成了且没有消息了代表我们的
channel开始空闲
                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();
                }
            }
        }
    }
    
        如果平台支撑sun的unsafe 则采用堆外内存去接受,否则用堆内存去接受
        public ByteBuf ioBuffer(int initialCapacity) {
        if (PlatformDependent.hasUnsafe()) {
            return directBuffer(initialCapacity);
        }
        return heapBuffer(initialCapacity);
        
    }
    当是自动读取 且(没有获取更多的数据 或者尝试读取的字节等于最后读取的字节)且
    总消息数小于最大每次读取的消息数量且读取的总字节数大于0
    
    config.isAutoRead() &&
                   (!respectMaybeMoreData || maybeMoreDataSupplier.get()) &&
                   totalMessages < maxMessagePerRead &&
                   totalBytesRead > 0;
                   尝试读取的字节等于最后读取的字节
                       public boolean get() {
                return attemptedBytesRead == lastBytesRead;
            }
        
当读完之后进行record操作,sizeTable 在512大小前按照16递增,到达51后按照*2递增     
               public void readComplete() {
            record(totalBytesRead());
        }
                  private void record(int actualReadBytes) {
            if (actualReadBytes <= SIZE_TABLE[max(0, index - INDEX_DECREMENT - 1)]) {
                if (decreaseNow) {
                    index = max(index - INDEX_DECREMENT, minIndex);
                    nextReceiveBufferSize = SIZE_TABLE[index];
                    decreaseNow = false;
                } else {
                    decreaseNow = true;
                }
            } else if (actualReadBytes >= nextReceiveBufferSize) {
                index = min(index + INDEX_INCREMENT, maxIndex);
                nextReceiveBufferSize = SIZE_TABLE[index];
                decreaseNow = false;
            }
        }

你可能感兴趣的:(Netty消息接受)