<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。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

东羚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值