Netty中JT808粘包和拆包

       开发部标JT808GPS平台,使用java语言开发网关程序,目前普遍使用Netty。众所周知,TPC编程要解决粘包和拆包问题。现提供一种解决方案如下: 

public class ProtocolDecoder extends ByteToMessageDecoder {

    private Logger logger = Logger.getLogger(ProtocolDecoder.class);

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        if (in == null) {
            return;
        }
        in.markReaderIndex();
        ByteBuf byteBuf = in.asReadOnly();
        byteBuf.markReaderIndex();
        while (in.isReadable()) {
            in.markReaderIndex();
            int packetBeginIndex = in.readerIndex();
            byte tag = in.readByte();
            // 搜索包的开始位置
            // 处理黏包和拆包
            if(tag==0x7E){
                if(!in.isReadable()){
                    in.resetReaderIndex();
                    return;
                }
                else{
                    tag = in.readByte();
                    // 防止是两个0x7E,取后面的为包的开始位置
                    // 寻找包的结束
                    while (tag != 0x7E) {
                        if (in.isReadable() == false) {
                            in.resetReaderIndex(); // 没有找到结束包,等待下一次包
                            // logger.error("半包:"+Tools.toHexString(data));
                            return;
                        }
                        tag = in.readByte();
                    }
                    int pos = in.readerIndex();
                    int packetLength = pos - packetBeginIndex;
                    if (packetLength > 2) {
                        byte[] tmp = new byte[packetLength];
                        in.resetReaderIndex();
                        in.readBytes(tmp);
                        //logger.error("收到数据 = " +  Tools.toHexString(tmp));
                        T808Message message = new T808Message();
                        message.readFromBytes(tmp);
                        out.add(message); // 触发接收Message的事件
                        // return message;
                    } else {
                        // 说明是两个0x7E
                        logger.error("收到2个7E,Index:" + in.readerIndex() + " 长度 = " + packetLength + " 末尾数据 = " +  Tools.toHexString(new byte[]{tag}));
                        in.resetReaderIndex();
                        in.readByte(); // 两个7E说明前面是包尾,后面是包头
                    }
                }
            }else if (in.isReadable() && byteBuf.isReadable()){
                byte[] bytes = new byte[byteBuf.readableBytes()];
                byteBuf.readBytes(bytes);
                logger.error( "(" + ctx.channel().id().asLongText() + "," + ctx.channel().remoteAddress() + ") Index:" + in.readerIndex() + " 存在非法数据:" + Tools.toHexString(bytes));
            }
        }
        return;
    }
}

Netty的TCP粘包拆包问题是由于底层的TCP协议无法理解上层的业务数据而导致的。为了解决这个问题,Netty提供了几种解决方案。其,常用的解决方案有四种[1]: 1. 固定长度的拆包器(FixedLengthFrameDecoder):将每个应用层数据包拆分成固定长度的大小。这种拆包器适用于应用层数据包长度固定的情况。 2. 行拆包器(LineBasedFrameDecoder):将每个应用层数据包以换行符作为分隔符进行分割拆分。这种拆包器适用于应用层数据包以换行符作为结束符的情况。 3. 分隔符拆包器(DelimiterBasedFrameDecoder):将每个应用层数据包通过自定义的分隔符进行分割拆分。这种拆包器适用于应用层数据包以特定分隔符作为结束标志的情况。 4. 基于数据包长度的拆包器(LengthFieldBasedFrameDecoder):将应用层数据包的长度作为接收端应用层数据包的拆分依据。根据应用层协议包含的数据包长度进行拆包。这种拆包器适用于应用层协议包含数据包长度的情况。 除了使用这些拆包器,还可以根据业界主流协议的解决方案来解决粘包拆包问题[3]: 1. 消息长度固定:累计读取到长度和为定长LEN的报文后,就认为读取到了一个完整的信息。 2. 使用特殊的分隔符:将换行符或其他特殊的分隔符作为消息的结束标志。 3. 在消息头定义长度字段:通过在消息头定义长度字段来标识消息的总长度。 综上所述,Netty提供了多种解决方案来解决TCP粘包拆包问题,可以根据具体的业务需求选择合适的解决方案[1][3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值