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

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

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

这种自定义的,我一般使用 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用起来很简单,但数据还是要小心处理。


©著作权归作者所有:来自51CTO博客作者mb5fdb0a4002420的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 基于数据库实现分布式锁
  2. 多种详细讲解小程序页面传值
  3. 命名空间与数据库基础
  4. PHP基础知识:命名空间的使用、自动加载器和数据库操作
  5. Symfony的学习
  6. 全息电力行业解决方案
  7. Druid源码分析与架构介绍
  8. 【Nest教程】数据验证class-validator
  9. 讲一讲ES6新增的两种数据结构Map和Set

随机推荐

  1. 现代 PHP 新特性 —— 闭包
  2. Mysql PHP生成的表:不能使用表
  3. PHP如何检查MySQLi查询是否需要关闭?
  4. 几个有用的php字符串过滤,转换函数代码
  5. 使用/发送POST数据时的libcurl C问题(不
  6. 在自建域名下调试php
  7. 高效的敏感词过滤方法(PHP)
  8. Symfony:我可以从Type / Form返回null吗?
  9. PHP - 将字符串转换为键值数组
  10. ajax在php页面上获得一个值的结果