class SignalobardMsgReadHandler : public SessionVectChar::ReadHandler
{
public:
  SignalobardMsgReadHandler() = delete;

SignalobardMsgReadHandler(SignalobardMsgReadHandler _in v) = delete;

SignalobardMsgReadHandler(sNetPack * _in data_ptr, size_t _in package_size = sizeof(sNetPack) )
    : last_time_(bzrobot::Now())
    , data_ptr_(data_ptr)
    , package_size_one_(package_size)
    , package_check_sum_(0)
    , cache_buffer_size_(0)
    , cache_buffer_()
  {
  }

virtual ~SignalobardMsgReadHandler()
  {
  }

inline int GetPackHeadFirstIndex( char buffer[], int one_package_size, unsigned char package_head_value )
  {
      int continue_equal_times = 0;
      for ( int i = 0; i < one_package_size; ++i )
      {
          if ( (unsigned char)buffer[i] == package_head_value )
          {
              ++continue_equal_times;
              if ( continue_equal_times == PackageHeadByte_ )
              {
                  return (i-(PackageHeadByte_-1));
              }
          }
          else
          {
              continue_equal_times = 0;
          }
      }
      return -1;
  }

unsigned short CalculateCheckSum ( char buffer_[], int package_size )
  {
      unsigned short check_sum = 0;
      for ( int i = 0; i < package_size-2; ++i )
      {
          check_sum += (unsigned char)buffer_[i];
      }
      return check_sum;
  }

bzrobot::Duration _rt BlankTime() const
  {
    return bzrobot::Now() - last_time_;
  }

protected:
  bzrobot::Result _rt RunMain(typename SessionVectChar::ReadHandler::OutputType _ut output,
                              typename SessionVectChar::ReadHandler::InputType _in input,
                              typename SessionVectChar::ReadHandler::OptionType _in option) final
  {
    last_time_ = bzrobot::Now();
    if(!data_ptr_)
    {
      return BZROBOT_SIGNAL_BOARD_MSG_ERROR;
    }
    TO_2_BYTE WORDtemp;

const std::vector<char>& input_data = input;
    //存包,然后根据包长决定是否取包,多包时取用最新包
    memcpy ( &cache_buffer_[cache_buffer_size_], input_data.data(), input_data.size() );
    cache_buffer_size_ = cache_buffer_size_ + input_data.size();
    //只要缓存长度大于单个包长度,即循环进行取包,以防缓存数据堆积
    while ( cache_buffer_size_ >= package_size_one_ )
    {
        //获取数据包头在缓存中的位置
        int pack_head_index = GetPackHeadFirstIndex ( cache_buffer_, package_size_one_, PackageHeadValue_ );
        //未找到包头,丢弃该部分,返回等待新的接收数据
        if ( pack_head_index == -1 )
        {
            BZROBOT_WARNNING("SiganlBoardMsg: Not find pack head index");
            cache_buffer_size_ = cache_buffer_size_ - ( pack_head_index + package_size_one_ );
            return BZROBOT_SIGNAL_BOARD_MSG_ERROR;
        }
        //找到包头,且缓存长度足够取包
        if ( pack_head_index + package_size_one_ <= cache_buffer_size_ )
        {
            memcpy( WORDtemp.b, &cache_buffer_[pack_head_index + package_size_one_ - 2], 2 );
            //确认包校验和是否相等:相等取出数据,将取出的包段及其之前的部分丢弃
            if ( CalculateCheckSum( cache_buffer_, package_size_one_ ) == WORDtemp.data16 )
            {
                memcpy(data_ptr_, &cache_buffer_[pack_head_index], package_size_one_);
                cache_buffer_size_ = cache_buffer_size_ - ( pack_head_index + package_size_one_ );
            }
            //确认包校验和是否相等:不相等取出数据,将该包段及其之前的部分丢弃
            else
            {
                BZROBOT_WARNNING("SiganlBoardMsg: Check sum not equal");
                cache_buffer_size_ = cache_buffer_size_ - ( pack_head_index + package_size_one_ );
            }
        }
        //找到包头,但缓存长度不够取包,丢弃包头之前的部分
        else
        {
            BZROBOT_WARNNING("SiganlBoardMsg: Not whole package");
            cache_buffer_size_ = cache_buffer_size_ - pack_head_index;
        }
    }
    return BZROBOT_SIGNAL_BOARD_MSG_SUCCEED;
  }

sNetPack * data_ptr_;
  size_t              package_size_one_;
  size_t              cache_buffer_size_;
  const unsigned char PackageHeadValue_ = 0xA5;
  const int           PackageHeadByte_ = 4;
  const static int    CacheBufferMaxSize_ = 1024;
  char                cache_buffer_[CacheBufferMaxSize_];
  unsigned short      package_check_sum_;
  bzrobot::Time       last_time_;
};

信号板拼包:数组方式(bug长度只是截短,并未清空,若之后拷贝数据长度小于之前数据长度,老数据会接在后面)的更多相关文章

  1. c语言数据拼包

    单片机数据拼包 对于数据包拼包方式常规方式有: 数组 指针 结构体 流 下文将此三种方式分别列举此数据包的实现. 然后对比优缺点. 本文举例数据包协议: 包头 长度Length 消息类型 消息序列号S ...

  2. Mina框架断包、粘包问题解决方式

    Mina框架断包.粘包问题解决方式 Apache Mina Server 是一个网络通信应用框架,也就是说,它主要是对基于TCP/IP.UDP/IP协议栈的通信框架(当然.也能够提供JAVA 对象的序 ...

  3. TCP与UDP的不同接包处理方式

    TCP与UDP的不同接包处理方式 1.UDP发包的问题问:udp 发送两次数据,第一次 100字节 ,第二次200字节, 接包方一次recvfrom( 1000 ), 收到是 100,还是200,还是 ...

  4. 数组方式使用jQuery对象

    一. 使用jQuery选择器获取结果是一个jQuery对象.然而,jQuery类库会让你感觉你正在使用一个定义了索引和长度的数组.在性能方面,建议使用简单的for或者while循环来处理,而不是$.e ...

  5. centos7 使用 omnibus包安装方式,安装 gitlab7.4

    centos7 使用 omnibus包安装方式,安装 gitlab7.4 1: gitlab是一个开源的软件,类似于github.com那样的git代码管理仓库: 官网 https://about.g ...

  6. 在centos使用rpm包的方式安装mysql,以及更改root密码

    在centos使用rpm包的方式安装mysql,对于centos官方实际推荐使用yum进行安装,下载安装的方式主要用于内网服务器不能连接外网yum源的情况. 下载包 首先根据centos版本在mysq ...

  7. Redis入门 – Jedis存储Java对象 - (Java序列化为byte数组方式)

    Redis入门 – Jedis存储Java对象 - (Java序列化为byte数组方式) 原文地址:http://alanland.iteye.com/admin/blogs/1600685(欢迎转载 ...

  8. Thinkphp框架拓展包使用方式详细介绍--验证码实例(十一)

    原文:Thinkphp框架拓展包使用方式详细介绍--验证码实例(十一) 拓展压缩包的使用方式详细介绍 1:将拓展包解压:ThinkPHP3.1.2_Extend.zip   --> 将其下的 \ ...

  9. POST请求中参数以form data和request payload形式+清空数组方式

    测试与服务端ajax时用的dva封装的request方法,而后端怎么也拿不到参数.结果返现参数在request payload里. HTTP POST表单请求提交时:Content-Typeappli ...

随机推荐

  1. memcache 协议 && Golang实现

    https://github.com/quguolin/memcache 一:Error ERROR\r\n 客户端发送了一个不存在的命令 CLIENT_ERROR\r\n 客户端发送了一个不符合协议 ...

  2. 20181205(模块循环导入解决方案,json&pickle模块,time,date,random介绍)

    一.补充内容 循环导入 解决方案: 1.将导入的语句挪到后面. ​ 2.将导入语句放入函数,函数在定义阶段不运行 #m1.pyprint('正在导入m1')   #②能够正常打印from m2 imp ...

  3. Educational Codeforces Round 53 (Rated for Div. 2) C Vasya and Robot 二分

    题目:题目链接 思路:对于x方向距离与y方向距离之和大于n的情况是肯定不能到达的,另外,如果n比abs(x) + abs(y)大,那么我们总可以用UD或者LR来抵消多余的大小,所以只要abs(x) + ...

  4. 《鸟哥的Linux私房菜》学习笔记(1)——文件与目录

    在Linux中,任何设备都是文件,不仅如此,连数据通信的接口也有专门的文件负责.可以说,一切皆文件,目录也是一种文件,是路径映射.因此,文件系统是Linux的基础. 一.文件与目录管理命令 1.ls( ...

  5. Prolog&Epilog

    这篇博客会简单介绍一下Prolog&Epilog 然后再简单介绍下我对于程序在计算机中到底如何运行的一些理解(因为自己之前也从来没有接触过这些方面的知识,所以如果有讲的不对的地方希望大家能够帮 ...

  6. Java做爬虫也很方便

    首先我们封装一个Http请求的工具类,用HttpURLConnection实现,也可以用HttpClient, 或者直接用Jsoup来请求. 工具类实现比较简单,就一个get方法,读取请求地址的响应内 ...

  7. VMware Workstation 14 PRO 下安装Ubuntu 16.04 LTS教程

    一.准备好安装的VMware Workstation 14 PRO 1.VMware Workstation 14 PRO下载链接:http://rj.baidu.com/soft/detail/13 ...

  8. day03_12 缩进介绍

    python比较变态,必须缩进,而C可以不缩进,世界上只有python这门语言要求必须缩进 tab键是缩进,shift+tab往左移动 SyntaxError:invalid syntax 语法错误 ...

  9. 阿里云 fatal: Authentication failed 退出码 128

    阿里云拉取代码时需要输入的用户名密码 跟我们登录aliyun的时候的账号密码不一样,需要先重置一下的,重置之前要配置好邮箱 https://code.aliyun.com/profile/passwo ...

  10. Windows杂技

    WINDOWS下 ,在某目录下按住shift加鼠标右键,可以直接有当前目录的dos窗口 win10不能用 解决办法是在当前文件夹的地址栏输入cmd然后回车 发现Powershell可以当作dos执行相 ...