文档章节

十六进制指令FF转义FE01

S
 Sieg_Chen
发布于 2018/02/26 22:09
字数 1017
阅读 112
收藏 0

数据帧格式如下表所示,数据帧开始标志和帧结束标志为FFH,其他字段不能出现FFH,如果数据确实为FFH,需对其进行转义处理。

发送数据时,如果在其它字段中出现FFH字节时,将FFH分解为FEH和01H这两个字节发送,如果在其它字段出现FEH字节时,需将FEH分解为FEH和00H这两个字节来发送。

接收数据时,如果出现“FE 01”这样连续两个字节时将之合为一个字节FFH;如果出现“FE 00”这样连续两个字节时将之合为一个字节FEH。

注:发送数据帧时:先校验,后做转义处理;接收数据帧时:先做转义处理,再做校验。

/**
 * 指令内容转义工具类
 */
public class ESCUtil {

    /**
     * 数据帧编码,添加帧头,添加帧尾,添加校验,校验方式:异或校验
     *
     * @param ibuf        传入数组,不含帧序号
     * @param fram_num_yn 是否添加帧序号,0:添加帧序号,非0:不添加帧序号
     * @return
     */
    public static byte[] ptkCode(byte[] ibuf, int fram_num_yn) {

        /**
         * 校验位
         */
        byte chk;

        /**
         * 数组下标
         */
        int slen = 0;

        /**
         * 转义前数组长度
         */
        int ilen;

        /**
         *  帧内容数据最大长度
         */
        int SENDBUF_SIZE = 36;

        /**
         * 转义后的数组
         */
        byte[] returnBytes;

        /**
         * 中间量,动态添加
         */
        List<Byte> temp;

        /**
         * 传入参数检验
         */
        if (ibuf == null) {
            throw new IllegalInstructException("解析数据为空");
        }
        ilen = ibuf.length;

        //检查数据长度是否正确
        if (ilen > SENDBUF_SIZE) {
            throw new IllegalInstructException("解析数据长度不正确");//发送字节数超长
        }
        temp = new ArrayList<>();

        //加入帧头
//        temp[slen++] = -1;
//        temp[slen++] = -1;
        temp.add((byte) -1);
        temp.add((byte) -1);

        //添加帧序号
        if (fram_num_yn == 0) {
            temp.add((byte) 19);
            chk = 19;
        } else {
            chk = 00;
        }

        //拷贝数据,转义
        for (int i = temp.size(); i < ilen - 2; i++) {
            chk ^= ibuf[i];//异或校验
            if (ibuf[i] == -1) {
                temp.add((byte) -2);
                temp.add((byte) 1);
            } else if (ibuf[i] == -2) {
                temp.add((byte) -2);
                temp.add((byte) 0);
            } else {
                temp.add(ibuf[i]);
            }
        }

        // 校验位编码
        if (chk == -1) {
            temp.add((byte) -2);
            temp.add((byte) 1);
        } else if (chk == -2) {
            temp.add((byte) -2);
            temp.add((byte) 0);
        } else {
            temp.add(chk);
        }

//         添加帧尾
        temp.add((byte) -1);

        Object[] objs = temp.toArray();
        returnBytes = new byte[objs.length];
        for (int i = 0; i < objs.length; i++) {
            Byte bbyte = (Byte) objs[i];
            returnBytes[i] = bbyte.byteValue();
        }
        return returnBytes;
    }

    /**
     * 解析上传指令:进行数据包的解码工作,去头去尾,通过校验码判断数据包数据是否正确
     *
     * @param ibuf        传入的回复指令数组
     * @param fram_num_yn 解码后的帧内容是否包含帧序号,0:不包含帧序号,非0:包含帧序号
     * @throws Exception
     */
    public static byte[] pktDecode(byte[] ibuf, int fram_num_yn) {

        /**
         *转义前原始指令数组长度
         */
        int ilen;

        /**
         * 输入指令最大长度:全部为转义指令时
         */
        int PARSE_FRM_MAXLEN = 80;

        /**
         * 转义后帧内容长度
         */
        int SENDBUF_SIZE = 41;

        /**
         * 转移后帧内容
         */
        byte[] ReceiveBuf = new byte[SENDBUF_SIZE];


        /**
         * 回复指令下标
         */
        int slen = 0;

        /**
         * 校验码
         */
        byte Chk = 0;

        /**
         *帧内容开始位置
         */
        char start = 0;

        /**
         * 输出帧内容数组,不包含/帧序号
         */
        byte[] obuf;

        /**
         * 临时变量
         */
        List<Byte> tempList;

        if (ibuf == null) {
            throw new IllegalInstructException("传入数据为空");
        }
        ilen = ibuf.length;

        // 原始帧长度至少为5:2个字节帧头,1 个字节帧序号,1个字节校验位,1个字节帧尾
        if ((ilen < 5) || (ilen > PARSE_FRM_MAXLEN)) {
            throw new IllegalInstructException("解析数据长度不正确");
        }

        //检验帧头和者帧尾
        if (-1 != ibuf[0] || -1 != ibuf[ibuf.length - 1]) {
            throw new IllegalInstructException("无效的帧头或帧尾");
        }

        //检验是否包含帧序号,生成不同长度的帧内容数组
        if (fram_num_yn != 0) {
            obuf = new byte[SENDBUF_SIZE];
        } else {
            obuf = new byte[SENDBUF_SIZE - 1];
        }

        //帧内容开始位置下标
        if (ibuf[2] == -1) {
            start = 3;
        } else if (ibuf[1] == -1) {
            start = 2;
        } else {
            start = 1;
        }

        //取帧内容,去除帧头,帧尾
        for (int i = start; i < ibuf.length - 1; i++) {
            ReceiveBuf[slen] = ibuf[i];
            //转义操作:或
            if (-2 == ibuf[i]) {
                ReceiveBuf[slen] |= ibuf[i + 1];
                i++;
            }
            slen++;
        }


        //异或校验码
        for (int i = 0; i < slen - 1; i++) {
            Chk ^= ReceiveBuf[i];
        }

        //验证校验码
        if (Chk == ReceiveBuf[slen - 1]) {
            if (fram_num_yn != 0) {//包含帧序号
                for (int i = 0; i < slen; i++) {
                    obuf[i] = ReceiveBuf[i];
                }
            } else {//不包含帧序号{
                for (int i = 1; i < slen; i++) {
                    obuf[i - 1] = ReceiveBuf[i];
                }
            }
            //增加帧头、帧尾
            byte[] out = new byte[obuf.length + start + 1];
            for (int i = 0; i < start; i++) {
                out[i] = -1;
            }
            System.arraycopy(obuf, 0, out, 2, obuf.length);
            out[out.length - 1] = -1;
            return out;
        } else {
            throw new IllegalInstructException("校验失败!");
        }

    }
}

 

© 著作权归作者所有

S
粉丝 0
博文 9
码字总数 2145
作品 0
成都
程序员
私信 提问
keepalived简单描述和其功能的实现

一、相关概念: 在 keepalived中,一个是master,其他的都是backup vrrp:实现ip地址的高可用性,将除地址之外其他的功能也转移 通过状态的改变,keepalived检测到,执行相应的状态下定义的脚本...

窝心爱丨Xj
2018/06/26
0
0
利用无效字节码指令引发逆向工具崩溃(二)

上一节我们介绍了一种利用无效字节码指令引发逆向工具崩溃的方法。(http://www.oschina.net/question/2285044_237431)可惜的是大部分反编译工具已经修复了该bug。但是如果我们插入有效的字...

拉偶有所依
2015/05/28
179
2
Keepalived+lvs 双机热备

Keepalived 双机热备 使用 Keepalived 做双机热备非常简单,经常和 LVS 搭配来实现高可用负载平衡方案 1. Master / Slave 首先准备两台测试服务器和一个虚拟IP。 Server A: 192.168.1.10 (主...

阳光蜜汁
2017/08/24
0
0
php---------字符串转义函数(addslashes,stripslashes)

在PHP中,有两个函数与字符串的转义有关,他们分别是 addslashes 和 stripslashes。 addslashes($string), 在指定的预定义字符前添加反斜杠 (),用于为存储在数据库中的字符串以及数据库查询...

切切歆语
2018/01/16
0
0
Android 的透明色的代码

黑色的十六进制色为#000000 要为其加上透明色则为:#(00-ff)000000即#(0-255)000000 其中全透明即为0阶,完全不透明即为255阶 因为0的十六进制为0;127的十六进制为7f,255的十六进制为ff 因此...

ForingY
2016/12/09
6
0

没有更多内容

加载失败,请刷新页面

加载更多

基础工具类

package com.atguigu.util;import java.sql.Connection;import java.sql.SQLException;import java.util.Properties;import javax.sql.DataSource;import com.alibaba.druid......

architect刘源源
25分钟前
29
0
P30 Pro劲敌!DxO官宣新机:排行榜又要变

5月26日晚间,DxOMark官方推特预告,将在5月27日公布一款新机型的DxOMark评分,猜猜是哪款? 网友猜想的机型有:红米K20、谷歌Pixel 3a、索尼Xperia 1、诺基亚9 PureView等。 DxOMark即将公布...

linux-tao
昨天
6
0
Ubuntu18.04.2窗口过小不能自适应(二次转载)

解决Ubuntu在虚拟机窗口不能自适应 2018年09月06日 16:20:08 起不了名儿 阅读数 855 此博文转载:https://blog.csdn.net/nuddlle/article/details/77994080(原地址) 试了很多办法这个好用 ...

tahiti_aa
昨天
2
0
死磕 java同步系列之CountDownLatch源码解析

问题 (1)CountDownLatch是什么? (2)CountDownLatch具有哪些特性? (3)CountDownLatch通常运用在什么场景中? (4)CountDownLatch的初始次数是否可以调整? 简介 CountDownLatch,可以...

彤哥读源码
昨天
4
0
Nginx提供下载apk服务

有时候我们可能需要提供文件或者其他apk下载链接,通过 nginx 配置可以很简单地实现。 server {    listen 80;    server_name download.xxx.com;    root app;    locati...

Jack088
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部