zoukankan      html  css  js  c++  java
  • 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 == '
    ') {
                        return i;
                    } else if (b == '
    ' && i < n - 1 && buffer.getByte(i + 1) == '
    ') {
                        return i;  // 
    
                    }
                }
                return -1;  // Not found.
            }
            2.然后读取数据bytes 转换成对象返回,容错处理暂时不分析 核心代码
            
                 if (eol >= 0) {
                    final ByteBuf frame;
                    final int length = eol - buffer.readerIndex();
                    final int delimLength = buffer.getByte(eol) == '
    '? 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;
            }
  • 相关阅读:
    导出表格,导出表格为excel,导出表格带样式,怎么导出表格数据为excel并且带样式呢
    webpack打包文件 可以npm cdn使用
    Webpack的externals的使用
    如何在微信小程序中使用iconfont
    如何发布和取消发布 NPM 包?
    js中数组对象去重的方法
    小程序列表性能优化
    wepy全局拦截器
    js中prototype与__proto__的关系详解
    JavaScript中本地对象、内置对象和宿主对象
  • 原文地址:https://www.cnblogs.com/solq/p/4307284.html
Copyright © 2011-2022 走看看