TCP通信中的数据包解析(处理拆包粘包)

这个解码器最主要是解决TCP粘包拆包问题

package com.wunaozai.iot.nettyplatform.code;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

/**
 * 自定义协议解析
 * @author Administrator
 *
 */
public class SmartIotDecoder extends ByteToMessageDecoder {


    private static final Logger log = LoggerFactory.getLogger(SmartIotDecoder.class);

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
        log.debug("启动解码器...");
        log.debug("目前数据缓存大小: " + buffer.readableBytes());
        // 刻度长度必须大于基本最小长度
        if(buffer.readableBytes() >= SmartIotProtocol.MIN_LEN){
            log.debug("符合最小长度,进行解析");
            //防止socket字节流攻击、客户端传来的数据过大,这里需要对数据进行过滤掉
            if(buffer.readableBytes() >= 4096){
                buffer.skipBytes(buffer.readableBytes());
                return ;
            }

            //记录包头开始位置
            int beginReader = 0;
            while(true){
                beginReader = buffer.readerIndex(); //记录包头开始位置
                buffer.markReaderIndex(); //标记包头开始index
                //读取协议开始标志
                if(buffer.readShort() == SmartIotProtocol.START){
                    break; //如果是开始标记,那么就结束查找
                }

                //如果找不到包头,这里要一个一个字节跳过
                buffer.resetReaderIndex();
                buffer.readByte();

                //当跳过后,如果数据包又不符合长度的,结束本次协议解析
                if(buffer.readableBytes() < SmartIotProtocol.MIN_LEN){
                    return ;
                }
            }

            short flowid = buffer.readShort();
            byte version_major = buffer.readByte();
            byte version_minor = buffer.readByte();
            byte second = buffer.readByte();
            byte minute = buffer.readByte();
            byte hour = buffer.readByte();
            byte day = buffer.readByte();
            byte month = buffer.readByte();
            byte year = buffer.readByte();
            byte[] src = new byte[6];
            src[0] = buffer.readByte();
            src[1] = buffer.readByte();
            src[2] = buffer.readByte();
            src[3] = buffer.readByte();
            src[4] = buffer.readByte();
            src[5] = buffer.readByte();
            byte[] dest = new byte[6];
            dest[0] = buffer.readByte();
            dest[1] = buffer.readByte();
            dest[2] = buffer.readByte();
            dest[3] = buffer.readByte();
            dest[4] = buffer.readByte();
            dest[5] = buffer.readByte();
            short data_len = buffer.readShort();
            if(buffer.readableBytes() < data_len + 4){
                //还原读指针
                buffer.readerIndex(beginReader);
                return ;
            }
            byte cmd = buffer.readByte();
            byte[] data = null;
            if(data_len > 0){
                //读取应用数据单元
                data = new byte[data_len];
                buffer.readBytes(data);
            }

            byte checksum = buffer.readByte();
            short end = buffer.readShort();

            if(end == SmartIotProtocol.END){
                log.debug("完成解析,并输出.");
                SmartIotProtocol iot = new SmartIotProtocol();
                iot.setFlowid(flowid);
                iot.setVersion_major(version_major);
                iot.setVersion_minor(version_minor);
                iot.setSecond(second);
                iot.setMinute(minute);
                iot.setHour(hour);
                iot.setDay(day);
                iot.setMonth(month);
                iot.setYear(year);
                iot.setSrc(src);
                iot.setDest(dest);
                iot.setData_len(data_len);
                iot.setCmd(cmd);
                if(data_len > 0){
                    iot.setData(data);
                }else{
                    iot.setData(null);
                }
                iot.setChecksum(checksum);
                out.add(iot);
            }
        }
    }

}

原文地址:https://www.cnblogs.com/wunaozai/p/11403015.html

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值