一、设计需求(who 该算法用来解决什么问题)
1、 按照网关协议解析得到完整数据包
2、 简单 安全 高效
二、列影响量(why影响该算法的因素有哪些)
1、开始码2、结束码
3、协议长度
4、协议内容
5、游标
6、剩余可读内容长度
三、应用场景(what组合各种影响量的场景有哪些)
具体分析如下图:
四、抽象方法(how建立一个算法模型解决上述场景的问题)
java代码具体实现:
private class ReadThread extends Thread { @Override public void run() { super.run(); /**定义一个包的最大长度*/ int maxLength = 2048; /*** 完整包缓存区*/ byte[] buffer = new byte[maxLength]; /*** 每次收到实际长度*/ int available; /*** 当前已经收到包的总长度*/ int currentLength = 0; int headLength = 4; while(!isInterrupted()) { try { available = mInputStream.available(); if(available > 0){ //防止超出数组最大长度而溢出 if(available > maxLength - currentLength){ available = maxLength - currentLength; } mInputStream.read(buffer,currentLength,available); currentLength += available; } } catch (IOException e) { e.printStackTrace(); return; } int cursor = 0; //如果当前收到的包长度大于头长度则解析 while (currentLength > headLength){ //System.out.print("--->"+buffer[cursor]); //取到起始码 if((buffer[cursor] != 0x80) || (buffer[cursor + 1] != 0x80)){ --currentLength; ++cursor; continue; } //将两个字节的byte 16进制数 转换成一个int型的10进制数 得到协议长度 int protocolLength = ((buffer[cursor + 2] & 0xff) << 8) | (buffer[cursor + 3] & 0xff);//协议长度 // 如果内容包的长度大于最大内容长度或者小于等于0,则说明这个包有问题,丢弃(丢掉开始码) if (protocolLength <= 0 || protocolLength > maxLength) { cursor = cursor + 2; currentLength = currentLength - 2; break; } if(currentLength < protocolLength){//缓存区剩余内容不足协议内容,则跳出等待接受 break; } int current = currentLength;//继续解析查找结束码 int cor = cursor; while (current > 0){ //搜到结束码 if((buffer[cor] != 0x90) || (buffer[cor + 1] != 0x90)){ --current; ++cor; continue; } //偏移量补上一个结束码字节 ++cor; //搜到结束码组包拼接完整包 byte[] buf = new byte[protocolLength]; if(protocolLength == ((cor - cursor)+1)){ //完整包产生 System.arraycopy(buffer, cursor, buf, 0, protocolLength); //解析完整包 parsePack(buf); //缓冲区丢掉完整包数据,并继续接受 currentLength -= protocolLength; cursor += protocolLength; break; } //偏移量指到下次开始位置,并记录 ++cor; //搜到结束码后,不是完整包,直接丢掉 currentLength -= (cor - cursor); cursor += (cor - cursor); break; } //剩余内容搜完都没有找到结束码以后的操作 /** * 协议长度 出现问题:开始码以后的内容长度>2048字节,以后接受的字节都进不来缓冲区了? 解决方案:清空脏数据腾出缓存区 只要开始码以后的字节长度大于协议长度就认为包不正常不是完整包同时丢掉,进行下次重新搜索开始码 */ if((cor - cursor) > protocolLength ){//小于说明数据没收完不丢,大于才丢 //没有搜到结束码后,不是完整包,直接丢掉 currentLength -= (cor - cursor); cursor += (cor - cursor); } break; } //残留字节移到缓冲区首 if (currentLength > 0 && cursor > 0) { System.arraycopy(buffer, cursor, buffer, 0, currentLength); } } } }
五、理论验证(Check代入数据验证算法模型的正确性)
六、实验测试(Test编码/代入数据/白盒/黑盒测试)
一般来说需要编码实现该算法,覆盖应用场景组织测试数据,让系统自动遍历测试数据,检验算法的正确性。白盒测试有助于:跟踪系统的运行,遍历程序分支,还可以优化软件;黑盒测试有助于:快速查看结果,检查算法输出是否正确。往往实验会找出算法缺陷,此时根据反馈需要重新设计或修正。