其他分享
首页 > 其他分享> > <2021SC@SDUSC>netty常见编解码器(二)

<2021SC@SDUSC>netty常见编解码器(二)

作者:互联网

2021SC@SDUSC

文章目录

前言

在这一篇博客中,将会介绍netty的FixedLengthFrameDecoder类,实现了固定长度的解码,是解码器中最简单的一个,但是实用性不高,所以不常使用。

一、FiexedLengthFrameDecoder

package io.netty.handler.codec;

import static io.netty.util.internal.ObjectUtil.checkPositive;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;

import java.util.List;

public class FixedLengthFrameDecoder extends ByteToMessageDecoder {

    private final int frameLength;
    
    public FixedLengthFrameDecoder(int frameLength) {
        checkPositive(frameLength, "frameLength");
        this.frameLength = frameLength;
    }

    @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);
        }
    }
    
    protected Object decode(
            @SuppressWarnings("UnusedParameters") ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        if (in.readableBytes() < frameLength) {
            return null;
        } else {
            return in.readRetainedSlice(frameLength);
        }
    }
}

二、分析

在FixedLengthFrameDescoder类中,只有一个构造函数,public FixedLengthFrameDecoder(int frameLength),要求传入一个int类型的变量,并将传入的参数赋给frameLength,且因为frameLength是final变量,在实例被创建后,不允许再去修改它。frameLength代表每一个帧的字节大小,实际使用中,将受到的消息按照这个变量的大小,还原成原来的数据。
在该类中,有两个decode方法,分别是protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exceptionprotected Object decode( @SuppressWarnings("UnusedParameters") ChannelHandlerContext ctx, ByteBuf in) throws Exception,其中,前一个decode方法是从父类继承来的,根据模板方法,在netty收到消息时,会调用到这个方法,而在第一个decode方法中,调用了第二个decode方法。在这里,简单分析第二个decode方法。
其实,在第二个decode方法中,就是对传入的bytebuf判断它的可读字节有没有大于等于frameLength,即现在缓冲区中字节数量有没有可以构成一个帧,如果没有,就返回null,否则ByteBuf类的readRetainedSlice方法,将长度为frameLength的字节从缓冲区中读出,然后返回给调用该方法的地方。

三、使用

经过分析,可以看到,FixedLengthFrameDecoder类的实现较为简单,但是,因为它对数据的大小有严格的限制,所以很难有实际的应用。比如,在网络层协议中,数据的头部有一个Option可选项,因此头部的大小其实是不定长的,如果一定要采用FixedLengthFrameDecoder,那么它的frameLength必须大于等于有可能的最长帧的大小,这样,在传输实际长度小于这个值的帧时,必须使用填充数据,造成网络资源的浪费,而且,关于填充字符的选择,也有一些问题,比如,如果采用’\0’作为填充字符,但实际传输的有意义的数据中也包含了这个字符的情况,应该如何处理?

四、总结

在本篇博客中,简单地分析了netty提供的FixedLengthFrameDecoder类,这个类将收集到的消息按照长度划分成不同的等长的帧,从而解决了粘包半包的问题,但是,虽然它的实现很简单,但是,有较强的局限性,因此,不具有实用性。如果想要借助实现自己的协议,且不能保证数据的大小一致,不建议使用FixedLengthFramdeDecoder。

标签:netty,frameLength,2021SC,ctx,编解码器,FixedLengthFrameDecoder,decode,ByteBuf,SDUSC
来源: https://blog.csdn.net/vrpseva/article/details/121711059