如何解决netty自定义协议粘包分包问题

又一次发现公司同事用netty竟然都不处理粘包分包的问题,出了问题都不知道怎么回事,呵呵哒。sp厂商反馈数据已推送至我方提供的地址,但未收到我方的应答,正常推送了一次,又重试三次,都没有收到我方应答。

看了下代码,又跟踪了几条日志,发现sp数据确实有推送,只是我方解析失败。好多数据都是几条信息拼一起过来的,我方只按照头部长度解析了一条,导致许多数据都没有正常更新;还有部分数据是分两次过来的,本来应该放在一起解析一次,我方却解析了两次,自然失败了。

看了下报文约定,基本是这个样子,头部是总长度+固定的命令+序列号+报文数据。

如何解决netty自定义协议粘包分包问题

这种自定义的,我一般使用 ByteToMessageDecoder来处理,要注意结合自定义报文约定,这里主要判定头长度和指定命令。









































/*** 基本长度(4+4+12) 4:总长度 4:命令标识 12:序列号*/private static final int BASE_LENGTH = 20;
@Overrideprotected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {   LOG.debug("decode channelId:{}",ctx.channel().id().asShortText());   if (in.readableBytes() <= BASE_LENGTH) {       LOG.debug("readables:{} channelId:{}",in.readableBytes(),ctx.channel().id().asShortText());       return;   }   int length, command;   while (true) {       in.markReaderIndex();       length = in.readInt();       command = in.readInt();       LOG.debug("length:{},command:{}, channelId:{}",length,command,ctx.channel().id().asShortText());       if (length > BASE_LENGTH && command == 0xF) {           LOG.debug("find command:{},channelId:{}",command,ctx.channel().id().asShortText());           break;       }       in.resetReaderIndex();       byte temp = in.readByte();       LOG.debug("skip a byte:{},channelId:{}",temp,ctx.channel().id().asShortText());
      if (in.readableBytes() <= BASE_LENGTH) {           LOG.debug("length:{} less than 20,channelId:{}",in.readableBytes(),ctx.channel().id().asShortText());           return;       }   }   in.resetReaderIndex();   if (in.readableBytes() < length) {       LOG.debug("can read:{} less than length:{},channelId:{}",in.readableBytes(),length,ctx.channel().id().asShortText());       return;   }   byte[] data = new byte[length];   in.readBytes(data);   LOG.debug("success,length:{} data:{},channelId:{}",length,data,ctx.channel().id().asShortText());   out.add(data);
比较简单,查看日志数据已经正常处理了,粘包数据会按报文约定分成多条数据处理,分包问题会等到数据到达指定长度时正确处理。netty用起来很简单,但数据还是要小心处理。


上一篇:设备用ws_flv为什么会有无法播放的情况?


下一篇:通知栏