当前位置: 首页 > 知识库问答 >
问题:

以面向对象的方式解析自定义数据包

龙越彬
2023-03-14
+-------+---------+---------+----------+------+
| Magic | Command | Options | Bodysize | Body |
+-------+---------+---------+----------+------+

(假设Magic是4个字节,Command是1个字节,Options是2个字节,Bodysize是4个字节,并且body本身的长度是可变的。)我如何在不使用任何第三方库的情况下解析它?

通常我会说,可以这样做来存储数据包数据:

#include <array>

class Packet {
public:

    explicit Packet(std::array<char, 10> headerbytes);

    void set_body(std::vector<char> data);
    std::vector<char> get_body();

    int8_t get_command();

    int16_t get_options();

    bool is_valid();

private:

    bool valid;

    int8_t _command;

    int16_t _options;

    int32_t body_size;

    std::vector<char> _data;

};

问题是,我首先提供头信息,然后以一种笨拙的方式添加正文数据。包对象有一个在不完整状态下可以访问的时间点。

我是用C++开发的,对于通过套接字发送和接收数据,使用了boost库。

共有1个答案

施振海
2023-03-14

如果您不想将数据读取绑定到一个完整的构造函数中(出于可以理解的分离关注点的原因),这是一个很好的非多态继承应用程序:

struct Header {
  static constexpr SIZE=10;
  Header(std::array<char,SIZE>);

  std::int8_t get_command() const {return command;}
  std::int16_t get_options() const {return options;}
  std::int32_t body_size() const {return length;}

private:
  std::int8_t command;
  std::int16_t options;
  std::int32_t length;
};

struct Packet : private Header {
  using Body=std::vector<char>;
  Packet(const Header &h,Body b) : Header(h),body(std::move(b))
  {if(body.size()!=body_size()) throw …;}

  using Header::get_command;
  using Header::get_options;
  const Body& get_body() const {return body;}

private:
  Body body;
};

// For some suitable Stream class:
Header read1(Stream &s)
{return {s.read<Header::SIZE>()};}
Packet read2(const Header &h,Stream &s)
{return {h,s.read(h.body_size())};}
Packet read(Stream &s)
{return read2(read1(s),s);}

请注意,私有继承防止未定义的行为通过头*删除数据包,以及肯定是无意的

const Packet p=read(s);
const Packet q=read2(p,s);   // same header?!

组合当然也会起作用,但可能会在完整的实现中导致更多的适配器代码。

 类似资料:
  • 问题内容: 我在解析给定的JSON数据时遇到了一个奇怪的问题。我有这个JSON结构: 如何使用Newtonsoft JSON.NET库解析此结构?我尝试使用自己的JsonConverter类: 但我有一个例外: 编辑:我也试图将其保存到字典: 但我还有一个例外: 我做错了什么?谢谢您的回答。 问题答案: 您似乎想要在JSON中将a表示为对象数组,其中每个嵌套对象都有一个来自字典的键和值。您可以使用

  • 我有一个C(而不是C)库,它一致地使用函数的第一个参数作为上下文对象(让我们调用类型),我想使用SWIG生成C#wrappers来保持这种调用风格(也就是说,不要把函数或多或少地孤立起来,而是把它们包装成某个类中的方法,并通过方法中的对象的引用访问)。 示例(C签名): 所需的C#API: 如果有人向我指出一个使用这种API风格的现有C(再次:不是C)库的SWIG生成的包装器,我也会很高兴;我什么

  • 问题内容: 有没有一种方法可以为查询对象创建自定义方法,以便您可以执行以下操作? 本质上在哪里 并能够过滤掉它吗? 问题答案: 您可以对基类进行子类化以添加自己的方法: 然后,您可以在创建会话时告诉SQLAlchemy使用此新查询类(此处的文档)。从您的代码看来,您可能正在使用Flask- SQLAlchemy,因此您可以按照以下步骤进行操作: 否则,您将参数直接传递给: 到目前为止,这个新的查询

  • 问题内容: 我的日期格式 (可以是其他任何 格式 ) ,我需要在date命令中使用它。不是美国格式。它是德语服务器,因为它是德语服务器。这在美国服务器上也无法正常工作。(语言环境设置为德语或美国) 这不起作用(包括错误): (日期:ungültigesDatum„ Do 19 Dez 2013 22:33:28 CET“ =) 困难在于我不知道以后将使用哪种语言环境,甚至不知道日期格式,因为用户可

  • 本文向大家介绍PHP面向对象教程之自定义类,包括了PHP面向对象教程之自定义类的使用技巧和注意事项,需要的朋友参考一下 那怎么开始设计一个合格的类呢,一开始就写class{}的都错了,正确的是什么都不写,而是假设这个类已经存在,这个对象已经存在,各种属性方法都已经有了,在这个完全的假设下想象下这个对象应该怎么用,例如我们制作一个缩略图的类,我们希望封装成一个类,方便下次使用,我们首先需要明确对象是

  • 前言 类与实例: 类的声明 生成实例 类与继承: 如何实现继承:继承的本质就是原型链 继承的几种方式 类的定义、实例化 类的定义/类的声明 方式一:用构造函数模拟类(传统写法) function Animal1() { this.name = 'smyhvae'; //通过this,表明这是一个构造函数 } 方式二:用 class 声明(ES6的写法) cl