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;

        }

 

你可能感兴趣的:(netty)