我正在以数据包(64 字节)的形式向设备发送和接收二进制数据。数据具有特定的格式,部分格式随着不同的请求/响应而变化。

现在我正在为接收到的数据设计一个解释器。简单地按位置读取数据就可以了,但是当我有十几种不同的响应格式时,看起来就不那么酷了。我目前正在考虑为此目的创建一些结构,但我不知道它如何与填充一起使用。

也许有更好的方法?


有关的:

有帮助吗?

解决方案

我之前已经做过无数次了:这是一个非常常见的场景。有很多事情我几乎总是做。

不要太担心让它成为最有效的东西。

如果我们确实花费了大量时间打包和拆包数据包,那么我们总是可以更改它以提高效率。虽然我还没有遇到过必须这样做的情况,但我还没有实现网络路由器!

虽然使用结构/联合是运行时最有效的方法,但它带来了许多复杂性:说服编译器打包结构/联合以匹配所需数据包的八位字节结构,努力避免对齐和字节顺序问题,以及缺乏安全性,因为没有或很少有机会对调试版本进行健全性检查。

我经常会得到一个包含以下几类内容的架构:

  • 数据包基类。任何公共数据字段都是可访问的(但不可修改)。如果数据不是以打包格式存储,则有一个虚拟函数将生成打包数据包。
  • 许多针对特定数据包类型的表示类,源自通用数据包类型。如果我们使用打包函数,那么每个表示类都必须实现它。
  • 可以从表示类的特定类型推断出的任何内容(即来自公共数据字段的数据包类型 ID)作为初始化的一部分进行处理,否则不可修改。
  • 每个表示类都可以从解包的数据包构建,或者如果数据包数据对该类型无效,则将正常失败。为了方便起见,可以将其封装在工厂中。
  • 如果我们没有可用的 RTTI,我们可以使用数据包 ID 来获取“穷人的 RTTI”,以确定对象真正属于哪个特定的表示类。

在所有这一切中,可以(即使只是为了调试版本)验证每个可修改的字段是否被设置为合理的值。虽然看起来工作量很大,但它使得很难获得无效格式的数据包,可以使用调试器轻松地通过肉眼检查预打包的数据包内容(因为它都是正常的平台本机格式变量)。

如果我们确实必须实现更高效的存储方案,那么也可以将其包含在这个抽象中,而几乎不需要额外的性能成本。

其他提示

您需要使用结构和/或联合。您需要确保连接两端的数据都正确打包,并且如果连接的任何一方有可能运行不同的网络字节顺序,您可能需要在每一端进行网络字节顺序的转换。字节顺序。

举个例子:

#pragma pack(push)  /* push current alignment to stack */
#pragma pack(1)     /* set alignment to 1 byte boundary */
typedef struct {
    unsigned int    packetID;  // identifies packet in one direction
    unsigned int    data_length;
    char            receipt_flag;  // indicates to ack packet or keep sending packet till acked
    char            data[]; // this is typically ascii string data w/ \n terminated fields but could also be binary
} tPacketBuffer ;
#pragma pack(pop)   /* restore original alignment from stack */

然后在分配时:

packetBuffer.packetID = htonl(123456);

然后收到时:

packetBuffer.packetID = ntohl(packetBuffer.packetID);

以下是一些讨论 字节顺序对齐和结构填充

如果您不打包结构,它最终会与字边界对齐,并且结构的内部布局及其大小将不正确。

在不知道数据的确切格式的情况下,很难说出最好的解决方案是什么。您考虑过使用工会吗?

我同意伍吉的观点。您还可以使用代码生成来执行此操作。使用一个简单的数据定义文件来定义所有数据包类型,然后对其运行 python 脚本以生成原型结构和每个数据包类型的序列化/反序列化函数。

这是一个“开箱即用”的解决方案,但我建议看看Python 构造 图书馆。

构造是用于解析和构建数据结构(二进制或文本)的Python库。它基于以声明性的方式定义数据结构的概念,而不是程序代码:更复杂的结构由简单的层次结构组成。这是第一个使解析乐趣的图书馆,而不是今天通常的头痛。

构造非常健壮和强大,仅仅阅读教程将帮助您更好地理解问题。作者还计划从定义自动生成 C 代码,因此绝对值得花精力去阅读。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top