Soluciones comunes y resumen del problema de medio paquete de netty sticky package

datos

Inicialización de la cadena del procesador Netty Análisis del código fuente
Proceso de lectura de la cadena del procesador Netty Proceso de ejecución de datos Análisis del código fuente
LineBasedFrameDecoder resuelve el paquete pegajoso Análisis del código fuente del
medio paquete Problema del medio paquete del paquete pegajoso netty Soluciones comunes y resumen
Diagrama y resumen de la arquitectura de la cadena del procesador Netty

El objetivo principal de resolver la bolsa adhesiva y la mitad de la bolsa.

Resolver el problema de los paquetes pegajosos y la mitad de los paquetes se trata en realidad de un tema, es decir, del paquete TCP, pasar un determinado byte como una marca, y luego el byte antes de la marca debe ser un byte deserializable Buff, para que pueda resolver la mitad del paquete pegajoso. Problema del paquete

Solución al paquete pegajoso

1. Especificando un número fijo de bytes como estándar de separación

2. Especifique caracteres especiales como estándar de separación

3. De forma predeterminada, el carácter de nueva línea se utiliza como estándar de separación (un caso en el que los caracteres especiales se designan como estándar de separación)

Diagrama de solución de la solución de paquete adhesivo

Inserte la descripción de la imagen aquí

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;
            } 
    }

Supongo que te gusta

Origin blog.csdn.net/weixin_38312719/article/details/108806499
Recomendado
Clasificación