Netty的自定义协议解码器

做了使用一个接收stm32单片机数据的项目,其中用到了netty自定义协议解码器,在此记录一下

  1. 自定义协议解码器继承 ByteToMessageDecoder
  2. 当bytebuf不包含整个协议消息长度时需要 return,直到bytebuf的长度包含整个协议的长度时,再进行解析
  3. stm32是小端数据,接收的时需要考虑大小端问题
  4. 当协议使用CRC32校验时,需注意stm的CRC32和主流CRC32有所不同,而且还有注意数据大小端问题。具体参考这篇文章

     PC端实现STM32硬件CRC32计算结果(基本原理)

下面是部分代码

public class MyProtocolByteDecoder extends ByteToMessageDecoder {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println(ctx.channel().remoteAddress().toString());
    }

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

    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        //防止byteBuf过大,超过最大值时清理
        clearRead(in);
        //消息小于接收的最小长度
        if (in.readableBytes() < 33) {
            return null;
        }
        //防止socket字节流攻击、客户端传来的数据过大,这里需要对数据进行过滤掉
        if(in.readableBytes() >= 40960){
            in.skipBytes(in.readableBytes());
            return null;
        }
        //记录消息头部位置
        int beginIndex;
        while (true) {
            beginIndex = in.readerIndex(); //记录包头开始位置
            //in.markReaderIndex(); //标记包头开始index
            //读取协议开始标志  //读取帧头字段 0-1
            short i = in.readShort();
            if((short)30959== i){
                break; //如果是开始标记,那么就结束查找
            }

            //如果读完了所有的数据 都没有获取到 消息头部 则判定所有消息为无效消息,直接放弃掉
            if (in.readableBytes() == 0) {
                return null;
            }

        }
        //数据类型 2  可以接收两种不同长度的数据
        byte type = in.readByte();
        int msgLength = 0;
        if (type ==1 ){
            msgLength = 3244;
        }else if (type ==2){
            msgLength = 28672;
        }
        //消息长度 这里已经读了三个字节所以要加3
        int i2 = in.readableBytes();
        if ( in.readableBytes()+3< msgLength) {
            //消息长度不够,还原readerIndex到消息头部的位置
            in.readerIndex(beginIndex);
            return null;
        }
    //下面就可以开始依据协议对数据进行解析了
   
}

 

posted @ 2021-08-20 17:45  南无象海豹  阅读(486)  评论(0)    收藏  举报