Netty 处理帧头帧尾,识别数据帧

本文介绍了一个基于Netty的ByteToMessageDecoder用于解析TCP/IP数据包,着重于如何处理帧头和帧尾,以提取有效信息的技术细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

处理帧头帧尾,识别有效信息


import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * TCP/IP数据解码器
 */
@Slf4j
@Component
public class MessageDecoderHandler extends ByteToMessageDecoder {

    private final ByteBuf header;
    private final ByteBuf ender;

    public MessageDecoderHandler() {
        this.header = Unpooled.buffer();
        header.writeByte(0xAA);
        header.writeByte(0x55);
        this.ender = Unpooled.buffer();
        ender.writeByte(0x55);
        ender.writeByte(0xAA);
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        // 显示十六进制的接收码
        log.info("协议收到数据为{}", ByteBufUtil.hexDump(in));
        // 调用decode方法,去除帧头和帧尾
        ByteBuf childBuf = decode(in);
        // 如果获得有效数据
        if (childBuf != null) {
            // 将有效数据备份加入接收列表
            out.add(childBuf.copy());
        }
    }

    protected ByteBuf decode(ByteBuf buf) {
        // 帧头起始位置
        int sliceStart = 0;
        // 帧尾起始位置
        int sliceEnd = 0;
        // 数据帧
        ByteBuf frame = null;
        // 帧头是存在
        if (header != null) {
            // 获取帧头位置
            int index = ByteBufUtil.indexOf(header, buf);
            // 帧头第一次出现位置找到
            if (index > -1 && index < buf.capacity()) {
                // 舍弃帧头前面的数据
                buf.readerIndex(index);
            }
            // 将帧头位置保存
            sliceStart = index;
        }
        // 帧尾存在
        if (ender != null) {
            // 获取帧尾的起始位置
            int endindex = ByteBufUtil.indexOf(ender, buf);
            // 保存帧尾的位置
            sliceEnd = endindex;
            // 帧尾找到,并且在帧头的后面
            if (endindex > -1 && endindex > sliceStart && endindex < buf.capacity()) {
                // 计算数据帧的长度:帧尾的起始位置-帧头的起始位置-帧头的长度
                assert header != null;
                int length = sliceEnd - sliceStart - header.readableBytes();
                // 获取数据子帧
                frame = buf.slice(sliceStart + header.readableBytes(), length);
                // 将reader索引设定到帧尾的后面
                buf.skipBytes(sliceEnd - sliceStart + ender.readableBytes());
                // 将数据帧返回
                return frame;
            }
        }
        //去掉剩余的垃圾数据
        if (sliceEnd == -1) {
            //将可读数据设置为0
            buf.skipBytes(buf.readableBytes());
        }
        return null;
    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值