netty 编/解码处理

    1.LineBasedFrameDecoder
        1.先找到结束符索引
        private static int findEndOfLine(final ByteBuf buffer) {
            final int n = buffer.writerIndex();
            for (int i = buffer.readerIndex(); i < n; i ++) {
                final byte b = buffer.getByte(i);
                if (b == ‘\n‘) {
                    return i;
                } else if (b == ‘\r‘ && i < n - 1 && buffer.getByte(i + 1) == ‘\n‘) {
                    return i;  // \r\n
                }
            }
            return -1;  // Not found.
        }
        2.然后读取数据bytes 转换成对象返回,容错处理暂时不分析 核心代码
        
             if (eol >= 0) {
                final ByteBuf frame;
                final int length = eol - buffer.readerIndex();
                final int delimLength = buffer.getByte(eol) == ‘\r‘? 2 : 1;

                if (length > maxLength) {
                    buffer.readerIndex(eol + delimLength);
                    fail(ctx, length);
                    return null;
                }

                if (stripDelimiter) {//是否连结束符返回 true 不返回
                    frame = buffer.readBytes(length);
                    buffer.skipBytes(delimLength);//跳过结束符数据
                } else {
                    frame = buffer.readBytes(length + delimLength);
                }

                return frame;
            }
    2.StringDecoder 分析 比较简单,ByteBuf 转换 string
        @Override
        protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
            out.add(msg.toString(charset));
        }
    3.DelimiterBasedFrameDecoder 自定义结束符解码分析,原理基本跟 LineBasedFrameDecoder 相同
        1.找到结束符 ByteBuf 对象,可支持多个
            int minFrameLength = Integer.MAX_VALUE;
            ByteBuf minDelim = null;
            for (ByteBuf delim: delimiters) {
                int frameLength = indexOf(buffer, delim);
                if (frameLength >= 0 && frameLength < minFrameLength) {
                    minFrameLength = frameLength;
                    minDelim = delim;
                }
            }
        2.然后读取数据bytes 转换成对象返回,容错处理暂时不分析 核心代码
            if (stripDelimiter) {//是否连结束符返回 true 不返回
                frame = buffer.readBytes(minFrameLength);
                buffer.skipBytes(minDelimLength);//跳过结束符数据
            } else {
                frame = buffer.readBytes(minFrameLength + minDelimLength);
            }

            return frame;
    4.FixedLengthFrameDecoder 比较简单
        protected Object decode(@SuppressWarnings("UnusedParameters") ChannelHandlerContext ctx, ByteBuf in) throws Exception {
            if (in.readableBytes() < frameLength) {
                return null;
            } else {
                return in.readBytes(frameLength);
            }
        }
    5.LengthFieldBasedFrameDecoder 在 FixedLengthFrameDecoder 基础上指定偏移读取长度,动态帧长度
        1.先看构造方法
        
            /**
     * Creates a new instance.
     *
     * @param byteOrder
     *        the {@link ByteOrder} of the length field
     * @param maxFrameLength
     *        the maximum length of the frame.  If the length of the frame is
     *        greater than this value, {@link TooLongFrameException} will be
     *        thrown.
     * @param lengthFieldOffset
     *        the offset of the length field
     * @param lengthFieldLength
     *        the length of the length field
     * @param lengthAdjustment
     *        the compensation value to add to the value of the length field
     * @param initialBytesToStrip
     *        the number of first bytes to strip out from the decoded frame
     * @param failFast
     *        If <tt>true</tt>, a {@link TooLongFrameException} is thrown as
     *        soon as the decoder notices the length of the frame will exceed
     *        <tt>maxFrameLength</tt> regardless of whether the entire frame
     *        has been read.  If <tt>false</tt>, a {@link TooLongFrameException}
     *        is thrown after the entire frame that exceeds <tt>maxFrameLength</tt>
     *        has been read.
     */
    public LengthFieldBasedFrameDecoder(  
        ByteOrder byteOrder, //传输方式,默认ByteOrder.BIG_ENDIAN
        int maxFrameLength, //帧最大长度
        int lengthFieldOffset,//数据长度偏移,忽略包头信息
        int lengthFieldLength,//数据长度大小
        int lengthAdjustment, //附加数据长度 默认0
        int initialBytesToStrip, 
        boolean failFast    //true 超过 maxFrameLength 长度会抛异常,看处理写得不清晰
    ) {
 

        this.byteOrder = byteOrder;
        this.maxFrameLength = maxFrameLength;
        this.lengthFieldOffset = lengthFieldOffset;
        this.lengthFieldLength = lengthFieldLength;
        this.lengthAdjustment = lengthAdjustment;
        lengthFieldEndOffset = lengthFieldOffset + lengthFieldLength;
        this.initialBytesToStrip = initialBytesToStrip;
        this.failFast = failFast;
    }
        2.核心分析    
      protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        if (discardingTooLongFrame) { //是否丢弃处理
            long bytesToDiscard = this.bytesToDiscard;
            int localBytesToDiscard = (int) Math.min(bytesToDiscard, in.readableBytes());
            in.skipBytes(localBytesToDiscard);//跳过丢弃数据
            bytesToDiscard -= localBytesToDiscard;
            this.bytesToDiscard = bytesToDiscard;//记录索引

            failIfNecessary(false);
        }
        //少于头信息忽略
        if (in.readableBytes() < lengthFieldEndOffset) {
            return null;
        }
        //计算实际数据读取索引
        int actualLengthFieldOffset = in.readerIndex() + lengthFieldOffset;
        //获取数据长度
        long frameLength = getFrameLength(in, actualLengthFieldOffset);

        if (frameLength < 0) {
            in.skipBytes(lengthFieldEndOffset);
            throw new CorruptedFrameException(
                    "negative pre-adjustment length field: " + frameLength);
        }
        // 帧总长度 = 数据长度+附加数据长度+ 偏移总长度
        frameLength += lengthAdjustment + lengthFieldEndOffset;

        if (frameLength < lengthFieldEndOffset) {
            in.skipBytes(lengthFieldEndOffset);
            throw new CorruptedFrameException(
                    "Adjusted frame length (" + frameLength + ") is less " +
                    "than lengthFieldEndOffset: " + lengthFieldEndOffset);
        }

        if (frameLength > maxFrameLength) {
            long discard = frameLength - in.readableBytes();
            tooLongFrameLength = frameLength;

            if (discard < 0) {
                // buffer contains more bytes then the frameLength so we can discard all now
                in.skipBytes((int) frameLength);
            } else {
                // Enter the discard mode and discard everything received so far.
                discardingTooLongFrame = true;
                bytesToDiscard = discard;
                in.skipBytes(in.readableBytes());
            }
            failIfNecessary(true);
            return null;
        }

        // never overflows because it‘s less than maxFrameLength
        int frameLengthInt = (int) frameLength;
        if (in.readableBytes() < frameLengthInt) {
            return null;
        }

        if (initialBytesToStrip > frameLengthInt) {
            in.skipBytes(frameLengthInt);
            throw new CorruptedFrameException(
                    "Adjusted frame length (" + frameLength + ") is less " +
                    "than initialBytesToStrip: " + initialBytesToStrip);
        }
        in.skipBytes(initialBytesToStrip);

        // extract frame
        int readerIndex = in.readerIndex();//当前读索引
        int actualFrameLength = frameLengthInt - initialBytesToStrip;//不清楚为什么-initialBytesToStrip
        ByteBuf frame = extractFrame(ctx, in, readerIndex, actualFrameLength); //拷贝数据
        in.readerIndex(readerIndex + actualFrameLength);//修改读索引
        return frame;
    }
    
    
        private long getFrameLength(ByteBuf in, int actualLengthFieldOffset) {
            in = in.order(byteOrder);
            long frameLength;
            switch (lengthFieldLength) {
            case 1:
                frameLength = in.getUnsignedByte(actualLengthFieldOffset);
                break;
            case 2:
                frameLength = in.getUnsignedShort(actualLengthFieldOffset);
                break;
            case 3:
                frameLength = in.getUnsignedMedium(actualLengthFieldOffset);
                break;
            case 4:
                frameLength = in.getUnsignedInt(actualLengthFieldOffset);
                break;
            case 8:
                frameLength = in.getLong(actualLengthFieldOffset);
                break;
            default:
                throw new Error("should not reach here");
            }
            return frameLength;
        }

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。