测试说明
注释代码37行,打开38行。

服务器正常启动,确认设备连接正常。
设备为客户端,每3秒向服务器发送心跳

模拟网络短暂不通,多个包同时到达,粘包情况:
拔掉网线30秒,插入网线。

代码如下

package mina;import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Arrays;import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.service.IoHandlerAdapter;
import org.apache.mina.core.session.AttributeKey;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
import org.apache.mina.transport.socket.nio.NioSocketAcceptor;public class Test {public static void main(String[] args) throws IOException {final byte[] key = { (byte) 0xb9, (byte) 0xda, 0x5e, 0x15, 0x46, 0x57, (byte) 0xa7, (byte) 0x8d, (byte) 0x9d,(byte) 0x84, (byte) 0x90, (byte) 0xd8, (byte) 0xab, 0x00, (byte) 0x8c, (byte) 0xbc, (byte) 0xd3, 0x0a,(byte) 0xf7, (byte) 0xe4, 0x58, 0x05, (byte) 0xb8, (byte) 0xb3, 0x45, 0x06, (byte) 0xd0, 0x2c, 0x1e,(byte) 0x8f, (byte) 0xca, 0x3f };NioSocketAcceptor acceptor = new NioSocketAcceptor();acceptor.getFilterChain().addFirst("codec", new ProtocolCodecFilter(new ProtocolEncoderAdapter() {@Overridepublic void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {System.out.println("编码:" + message);}}, new CumulativeProtocolDecoder() {@Overrideprotected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {System.out.println();System.out.println("长度:" + in.limit());System.out.println();IoBuffer ioBuffer = getContext(session).getIoBuffer();//IoBuffer ioBuffer = IoBuffer.allocate(100).setAutoExpand(true);while (in.hasRemaining()) {byte b = in.get();ioBuffer.put(b);System.out.print("【"+b+"】");if (b != 0x03 && b != 0x04) {continue;}byte[] array = ioBuffer.array();if (array[0] != 0x02) {System.out.println();System.out.println("=======================================");System.out.println("未知包" + ByteUtil.toHexStr(array));System.out.println("=======================================");throw new RuntimeException("================未知包================");}array = Arrays.copyOfRange(array, 1, ioBuffer.position() - 2);int temp1 = array.length / 32;int temp2 = array.length % 32;for (int i = 0; i < temp1; i++) {for (int j = 0; j < 32; j++) {array[i * 32 + j] ^= key[j];}}for (int j = 0; j < temp2; j++) {array[temp1 * 32 + j] ^= key[j];}System.out.println("");System.out.println("=======================================");System.out.println("解析到包:" + new String(array));System.out.println("=======================================");out.write(new String(array));ioBuffer.clear();System.out.println("返回true");return true;}System.out.println("返回false");return false;}private final AttributeKey CONTEXT = new AttributeKey(getClass(), "context");public Context getContext(IoSession session) {Context ctx = (Context) session.getAttribute(CONTEXT);if (ctx == null) {ctx = new Context();session.setAttribute(CONTEXT, ctx);}return ctx;}class Context {private IoBuffer ioBuffer = IoBuffer.allocate(100).setAutoExpand(true);public IoBuffer getIoBuffer() {return ioBuffer;}}}));acceptor.setHandler(new IoHandlerAdapter() {@Overridepublic void messageReceived(IoSession session, Object message) throws Exception {super.messageReceived(session, message);}});acceptor.bind(new InetSocketAddress(3333));}
}

打印如下


长度:53【2】【-35】【-65】【40】【124】【37】【50】【-99】【-18】【-8】【-80】【-95】【-71】【-101】【53】【-24】【-100】【-70】【110】【-51】【-44】【120】【102】【-43】【-41】【127】【50】【-32】【20】【62】【-7】【-85】【83】【-52】【-65】【100】【119】【35】【54】【-45】【-13】【-29】【-92】【-4】【-67】【-59】【103】【-8】【-44】【-23】【61】【0】【3】
=======================================
解析到包:device:ce41a05d id:0 cmd:408 value:beat~~ length:7
=======================================
返回true长度:256【2】【-35】【-65】【40】【124】【37】【50】【-99】【-18】【-8】【-80】【-95】【-71】【-101】【53】【-24】【-100】【-70】【110】【-51】【-44】【120】【102】【-43】【-41】【127】【50】【-32】【20】【62】【-7】【-85】【83】【-52】【-65】【100】【119】【35】【54】【-45】【-13】【-29】【-92】【-4】【-67】【-59】【103】【-8】【-44】【-23】【61】【0】【3】
=======================================
解析到包:device:ce41a05d id:0 cmd:408 value:beat~~ length:7
=======================================
返回true长度:256【2】【-35】【-65】【40】【124】【37】【50】【-99】【-18】【-8】【-80】【-95】【-71】【-101】【53】【-24】【-100】【-70】【110】【-51】【-44】【120】【102】【-43】【-41】【127】【50】【-32】【20】【62】【-7】【-85】【83】【-52】【-65】【100】【119】【35】【54】【-45】【-13】【-29】【-92】【-4】【-67】【-59】【103】【-8】【-44】【-23】【61】【0】【3】
=======================================
解析到包:device:ce41a05d id:0 cmd:408 value:beat~~ length:7
=======================================
返回true长度:256【2】【-35】【-65】【40】【124】【37】【50】【-99】【-18】【-8】【-80】【-95】【-71】【-101】【53】【-24】【-100】【-70】【110】【-51】【-44】【120】【102】【-43】【-41】【127】【50】【-32】【20】【62】【-7】【-85】【83】【-52】【-65】【100】【119】【35】【54】【-45】【-13】【-29】【-92】【-4】【-67】【-59】【103】【-8】【-44】【-23】【61】【0】【3】
=======================================
解析到包:device:ce41a05d id:0 cmd:408 value:beat~~ length:7
=======================================
返回true长度:256【2】【-35】【-65】【40】【124】【37】【50】【-99】【-18】【-8】【-80】【-95】【-71】【-101】【53】【-24】【-100】【-70】【110】【-51】【-44】【120】【102】【-43】【-41】【127】【50】【-32】【20】【62】【-7】【-85】【83】【-52】【-65】【100】【119】【35】【54】【-45】【-13】【-29】【-92】【-4】【-67】【-59】【103】【-8】【-44】【-23】【61】【0】【3】
=======================================
解析到包:device:ce41a05d id:0 cmd:408 value:beat~~ length:7
=======================================
返回true长度:256【2】【-35】【-65】【40】【124】【37】【50】【-99】【-18】【-8】【-80】【-95】【-71】【-101】【53】【-24】【-100】【-70】【110】【-51】【-44】【120】【102】【-43】【-41】【127】【50】【-32】【20】【62】【-7】【-85】【83】【-52】【-65】【100】【119】【35】【54】【-45】【-13】【-29】【-92】【-4】返回false长度:433【-67】【-59】【103】【-8】【-44】【-23】【61】【0】【3】
=======================================
未知包BD,C5,67,F8,D4,E9,3D,00,03,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
=======================================长度:53【2】【-35】【-65】【40】【124】【37】【50】【-99】【-18】【-8】【-80】【-95】【-71】【-101】【53】【-24】【-100】【-70】【110】【-51】【-44】【120】【102】【-43】【-41】【127】【50】【-32】【20】【62】【-7】【-85】【83】【-52】【-65】【100】【119】【35】【54】【-45】【-13】【-29】【-92】【-4】【-67】【-59】【103】【-8】【-44】【-23】【61】【0】【3】
=======================================
解析到包:device:ce41a05d id:0 cmd:408 value:beat~~ length:7
=======================================
返回true

解释
插入网线后,不打印日志。(模拟的,有时是马上就打印)
大约20秒后,瞬间收到5、60行日志。

一个心跳包已0x02开头、已0x03结尾,长度为53。

日志第2行:长度为53,表示这个包正常

日志第10行:长度为256,说明IoBuffer in一次从缓存读取256个字节,是4个心跳包加半个心跳包的长度。
代码:
41行,每次取一个字节
42行,保存字节到ioBuffer
45行,如果不是取到一个完整的包,继续保存字节到ioBuffer
60行,解码数据
79行,返回true
上级代码

protected CumulativeProtocolDecoder() {}public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {if (!session.getTransportMetadata().hasFragmentation()) {while (in.hasRemaining()) {/**当前读取到in的53的位置,还有剩余字节(共256),并且doDecode返回的true,则继续执行doDecode。CumulativeProtocolDecoder.decode(..)的上层为同步,所以这个没循环完,就算缓存还有新数据,也需要等待decode方法执行完才可以。上层代码: synchronized (session) {decoder.decode(session, in, decoderOut);}*/if (!doDecode(session, in, out)) {break;}}return;}boolean usingSessionBuffer = true;IoBuffer buf = (IoBuffer) session.getAttribute(BUFFER);

日志第18行:
从in的256的53位置继续读取53个字节,继续返回true

日志第26行:
从in的256的106位置继续读取53个字节,继续返回true

日志第34行:
从in的256的159位置继续读取53个字节,继续返回true

日志第34行:
从in的256的212位置继续读取53个字节,继续返回true

日志第42行:
从in的256的212位置继续读取44个字节,返回false
CumulativeProtocolDecoder() {
}
public void decode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
if (!session.getTransportMetadata().hasFragmentation()) {
while (in.hasRemaining()) {
/**
返回false,表示本方法执行完毕。如果有新包则在执行。
*/
if (!doDecode(session, in, out)) {
break;
}
}
return;
}

日志第42行:
本次长度433(上次心跳包的9个字节+新的8个心跳包的长度)
test.java.38行又重新创建的IoBuffer,通过0x03截取的时候,取到的是9个字节的长度。所以需要把IoBuffer放入session中,就可以连接上次取到的包加本次的9个字节,组合成一个完成的包。

mina框架CumulativeProtocolDecoder.doDecode方法浅析相关推荐

  1. Camera开发系列之六-使用mina框架实现视频推流

    章节 Camera开发系列之一-显示摄像头实时画面 Camera开发系列之二-相机预览数据回调 Camera开发系列之三-相机数据硬编码为h264 Camera开发系列之四-使用MediaMuxer封 ...

  2. 图文详解mina框架

    Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP.UDP/IP协议栈的通信框架(当然,也可以提供JAVA 对象的序列化服务.虚拟机管道通信服务等),M ...

  3. 异步爬虫框架与协程浅析

    异步爬虫框架与协程浅析 经典原文使用协成完成异步爬虫原文链接 根据分享原文链接. Python基于协程的实现,其实是利用了Python生成器的特性完成的,Python生成器的原理其实涉及到用户态绿色线 ...

  4. 基于MINA框架快速开发网络应用程序

    1.MINA框架简介  MINA(Multipurpose Infrastructure for Network Applications)是用于开发高性能和高可用性的网络应用程序的基础框架.通过使用 ...

  5. Mina框架项目运用

    近期最一个项目对通信要求比較严格,须要建立长连接,且能处理多并发,所以选择了Mina框架.以下就简单记录开发的过程吧: mina 开发须要的jar包: mina pc端通信: 服务端: package ...

  6. 搭建Apache Mina框架并实现Server与Client端的简单消息传递

    http://www.himigame.com/apache-mina/831.html :(作者新浪微博: @李华明Himi ) 转载自[黑米GameDev街区] 原文链接: http://www. ...

  7. 基于PHP+小程序(MINA框架)+Mysql数据库的食堂餐厅就餐预约小程序系统设计与实现

    项目背景和意义 目的:本课题主要目标是设计并能够实现一个基于微信高校食堂就餐预约小程序系统,前台用户使用小程序,小程序使用微信开发者工具开发:后台管理使用基PP+MySql的B/S架构,开发工具使用p ...

  8. 基于PHP+小程序(MINA框架)+Mysql数据库的旅游攻略小程序系统设计与实现

    项目背景和意义 目的:本课题主要目标是设计并能够实现一个基于微信景区景点旅游攻略小程序系统,前台用户使用小程序,小程序使用微信开发者工具开发:后台管理使用基PP+MySql的B/S架构,开发工具使用p ...

  9. 基于PHP+小程序(MINA框架)+Mysql数据库的新生自助报到小程序系统设计与实现

    项目背景和意义 目的:本课题主要目标是设计并能够实现一个基于微信小程序新生报到系统,前台用户使用小程序,后台管理使用基PHP+MySql的B/S架构:通过后台添加学校信息.分院信息.班级信息.老师信息 ...

  10. 基于PHP+小程序(MINA框架)+Mysql数据库的评选投票小程序系统设计与实现

    项目背景和意义 目的:本课题主要目标是设计并能够实现一个基于微信小程序评选投票系统,前台用户使用小程序,后台管理使用基PHP+MySql的B/S架构:通过后台添加资讯.管理上传投票信息.用户管理等:用 ...

最新文章

  1. 鸿蒙os操作系统合作伙伴,华为公布三大鸿蒙OS系统 已有大量合作伙伴进行开发...
  2. 使用Java对轨迹进行抽稀,并生成mvt(Map Vector Tile)瓦片
  3. 王者归来!2020 年 5 月编程语言排行榜,Python竟然排老三
  4. 已知两边和夹角求第三边长_数学九年级上册3.4.2节利用两边及夹角判定三角形相似微课视频|知识点...
  5. redis 保存 array list 区别_为什么Redis的RDB备份不用多线程实现CopyOnWrite?
  6. 网关限流(令牌桶算法)
  7. 剑客决斗(NYOJ 110)
  8. 5s的app显示无法连接服务器,苹果iphone5s手机无法连接App Store问题解决方法汇总...
  9. 关于Ubuntu中 E: Could not get lock /var/lib/dpkg/lock - open (11: Resource temporarily unavailable)解决方案
  10. QString::arg()//用字符串变量参数依次替代字符串中最小数值
  11. sql server实用工具sql prompt的安装与注册
  12. Sublime Text3报错:Error while loading PyV8 binary:exit code 3
  13. 番茄花园GHOST XP SP3 V1.61 Final纪念版 http://www.ghost2.cn
  14. appium的环境安装与架构
  15. MAC快捷键---8
  16. 数学7大定理比较,五点(驻、极、最、拐、间)比较,求极值问题(求根验证负数形式)
  17. idea发送请求提示 无法保留cookie.cookie storage file is included in ignored list:
  18. K8s 集群节点在线率达到 99.9% 以上,扩容效率提升 50%,我们做了这 3 个深度改造...
  19. QueryDSL 关于Q类找不到的问题
  20. method属性值为get提交表单信息,为什么在地址栏不会显示呢。

热门文章

  1. WindowsServer实训项目——第一章:安装与激活WindowsServer
  2. Java设计模式——简单工厂模式
  3. 不上班的活法,在家赚钱的副业兼职
  4. MTK手机官方ROM提取教程
  5. bl小说里面有个机器人管家_不久的未来 有个“机器人管家”或不再是梦想
  6. 使用CAD手机看图软件打开图纸压缩包的方法技巧
  7. ClientKey实现登录QQ空间,并设置背景音乐
  8. 隐藏窗口的任务栏图标
  9. chromeos java安装_谷歌最新系统ChromeOS安装体验,酷!
  10. css 清除表单样式,css form表单样式清除