如何解释C ++中的二进制数据?

时间:2009-05-12 11:48:17

标签: c++ embedded byte

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

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

也许有更好的方法?


相关:

5 个答案:

答案 0 :(得分:8)

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

举个例子:

#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);

以下是对EndiannessAlignment and Structure Packing

的一些讨论

如果你没有打包结构,它最终会与字边界对齐,结构的内部布局也会不正确。

答案 1 :(得分:3)

如果不了解数据的确切格式,很难说最佳解决方案是什么。你考虑过使用工会吗?

答案 2 :(得分:3)

我以前做过无数次:这是一种非常常见的情况。我实际上总是做很多事情。

不要过于担心使它成为最有效的东西。

如果我们花费大量时间来打包和解包数据包,那么我们总是可以将其更改为更高效。虽然我还没有遇到过我必须要做的情况,但我还没有实现网络路由器!

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

我常常使用包含以下几种内容的架构:

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

在所有这些中,有可能(即使仅用于调试版本)验证每个可修改的字段是否被设置为合理的值。虽然它可能看起来很多工作,但它使得格式化的数据包非常困难,可以使用调试器通过眼睛轻松检查预先打包的数据包内容(因为它全部采用普通的平台本机格式变量)。

如果我们确实需要实现更高效的存储方案,那么这种方案也可以包含在这种抽象中,只需要很少的额外性能。

答案 3 :(得分:1)

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

答案 4 :(得分:1)

这是一个“开箱即用”的解决方案,但我建议您查看Python construct库。

  

Construct是一个python库   解析和构建数据   结构(二进制或文本)。它是   基于定义数据的概念   结构以声明的方式,   而不是程序代码:更多   复杂结构由a组成   更简单的层次结构。就是这样   第一个使解析变得有趣的库,   而不是通常的头痛   今天。

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