ネットスティッキーパッケージハーフパッケージ問題の一般的な解決策と要約

データ

Nettyプロセッサチェーンの初期化ソースコード分析
Nettyプロセッサチェーン読み取りデータ実行プロセスソースコード分析
LineBasedFrameDecoderは、スティッキーパッケージハーフパッケージソースコード分析を解決します
ネティスティッキーパッケージハーフパッケージ問題の一般的な解決策と概要
Nettyプロセッサチェーンアーキテクチャの図と概要

スティッキーバッグとハーフバッグを解決する主な目的

スティッキーパケットとハーフパケットの問題を解決することは、実際にはテーマの周りです。つまり、TCPパケットから、特定のバイトをマークとして渡し、マークの前のバイトは逆シリアル化可能なバイトバフでなければなりません。スティッキーパケットの半分。パッケージの問題

スティッキーパッケージの解決策

1.分離基準として固定バイト数を指定する

2.分離標準として特殊文字を指定します

3.デフォルトでは、改行文字が分離標準として使用されます(特殊文字が分離標準として指定されている場合)

スティッキーパッケージソリューションのソリューション図

ここに画像の説明を挿入します

FixedLengthFrameDecoder

//截取固定长度的字节作为一个包

//子类解码实现,由ByteToMessageDecoder主流程的channelRead调用
//子类实现,只是截取FixedLength应该截取的字节长度
protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
    
    
    Object decoded = decode(ctx, in);
    if (decoded != null) {
    
    
        out.add(decoded);
    }
}

//截取定义长度的frameLength的Buff
//1.如果长度不够,那么不截取,直接返回null,不执行下去(半包)
//2.如果长度大于等于frameLength长度,截取frameLength长度字节的Buff(粘包)
protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
    
    
        if (in.readableBytes() < frameLength) {
    
    
            return null;
        } else {
    
    
            return in.readRetainedSlice(frameLength);
        }
    }

DelimiterBasedFrameDecoder

//根据指定的特殊字符分割作为一个包

//子类解码实现,由ByteToMessageDecoder主流程的channelRead调用
//子类实现,只是截取指定特殊字符前面的字节长度
protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
    
    
    Object decoded = decode(ctx, in);
    if (decoded != null) {
    
    
        out.add(decoded);
    }
}

protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
    
    
      
        int minFrameLength = Integer.MAX_VALUE;
        ByteBuf minDelim = null;
        for (ByteBuf delim: delimiters) {
    
    
            //找到特殊字符的字节内容长度,根据delim去截取
            int frameLength = indexOf(buffer, delim);
            if (frameLength >= 0 && frameLength < minFrameLength) {
    
    
                //minFrameLength表示这个包的长度
                minFrameLength = frameLength;
                //
                minDelim = delim;
            }
        }
        
        //minFrameLength是包长度
        //minDelimLength是指定特殊字符的长度
        //每次一帧长度为minFrameLength+minDelimLength
        if (minDelim != null) {
    
    
            if (stripDelimiter) {
    
    
                frame = buffer.readRetainedSlice(minFrameLength);
                buffer.skipBytes(minDelimLength);
            } else {
    
    
                frame = buffer.readRetainedSlice(minFrameLength + minDelimLength);
            }

            return frame;
        } 
    }

LineBasedFrameDecoder

//根据指定的特殊字符分割作为一个包

//子类解码实现,由ByteToMessageDecoder主流程的channelRead调用
//子类实现,只是截取换行符前的字节长度

@Override
protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
    
    
    Object decoded = decode(ctx, in);
    if (decoded != null) {
    
    
        out.add(decoded);
    }
}

//寻找到换行符然后截取子Buff
protected Object decode(ChannelHandlerContext ctx, ByteBuf buffer) throws Exception {
    
    
        //找到换行符的位置eol
        final int eol = findEndOfLine(buffer);
        if (!discarding) {
    
    
            if (eol >= 0) {
    
    
                final ByteBuf frame;
                //eol是换行符前面字节长度
              	//delimLength是换行符长度
                //截取的总长度是eol+delimLength
                final int length = eol - buffer.readerIndex();
                final int delimLength = buffer.getByte(eol) == '\r'? 2 : 1;

                if (stripDelimiter) {
    
    
                    //获取完整包字节
                    frame = buffer.readRetainedSlice(length);
                    //跳过换行符长度字节数
                    buffer.skipBytes(delimLength);
                } else {
    
    
                    frame = buffer.readRetainedSlice(length + delimLength);
                }

                return frame;
            } 
    }

おすすめ

転載: blog.csdn.net/weixin_38312719/article/details/108806499