【发布时间】:2019-09-11 01:43:19
【问题描述】:
我目前正在用 C++ 开发一些软件,用于发送和接收自定义数据包。我想以结构良好的方式解析和管理这些数据包。显然,我首先收到标题,然后是数据正文。主要问题是我不喜欢创建仅包含标头信息的数据包对象,然后再添加正文数据。解析和存储自定义数据包的优雅方式是什么?
以下是此类自定义数据包的粗略示意图:
+-------+---------+---------+----------+------+
| 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 库。
【问题讨论】:
-
“我不喜欢创建一个仅包含标头信息的 Packet-Object,然后再添加正文数据” - 为什么不呢?
-
您是否考虑过使用现有的广泛使用的序列化系统(例如 Google protobuf),而不是重新发明轮子?
-
@Jesper 我认为这将是一个糟糕的设计,因为可以在不完整的状态下访问该对象。我不确定什么是常见的做法,我也不知道什么是最好的设计选择。我正在考虑一些执行解析的数据包处理器和一个已填充且只有在填充了所有数据后才能访问的数据包数据容器
-
@rici 是的,我有,我更喜欢自己做。不是因为这一定更好,而是因为它帮助我加深了对这些东西如何工作以及它们是如何设计的理解。
-
@JesperJuhl 我更新了我的帖子并添加了更多信息。
标签: c++ parsing networking packet