我正在以数据包(64字节)向设备发送和接收二进制数据。数据具有特定格式,其中一部分因不同的请求/响应而异。
现在我正在为收到的数据设计一个解释器。简单地按位置读取数据是可以的,但是当我有十几种不同的响应格式时看起来并不那么酷。我目前正在考虑为此目的创建一些结构,但我不知道如何使用填充。
也许有更好的方法?
相关:
答案 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);
以下是对Endianness和Alignment and Structure Packing
的一些讨论如果你没有打包结构,它最终会与字边界对齐,结构的内部布局也会不正确。
答案 1 :(得分:3)
如果不了解数据的确切格式,很难说最佳解决方案是什么。你考虑过使用工会吗?
答案 2 :(得分:3)
我以前做过无数次:这是一种非常常见的情况。我实际上总是做很多事情。
不要过于担心使它成为最有效的东西。
如果我们花费大量时间来打包和解包数据包,那么我们总是可以将其更改为更高效。虽然我还没有遇到过我必须要做的情况,但我还没有实现网络路由器!
虽然在运行时使用结构/联合是最有效的方法,但它带来了许多复杂性:说服编译器打包结构/联合以匹配所需数据包的八位字节结构,努力避免对齐和endianness问题,以及缺乏安全性,因为没有或很少有机会对调试版本进行健全性检查。
我常常使用包含以下几种内容的架构:
在所有这些中,有可能(即使仅用于调试版本)验证每个可修改的字段是否被设置为合理的值。虽然它可能看起来很多工作,但它使得格式化的数据包非常困难,可以使用调试器通过眼睛轻松检查预先打包的数据包内容(因为它全部采用普通的平台本机格式变量)。
如果我们确实需要实现更高效的存储方案,那么这种方案也可以包含在这种抽象中,只需要很少的额外性能。
答案 3 :(得分:1)
我同意Wuggy。您也可以使用代码生成来执行此操作。使用简单的数据定义文件来定义所有数据包类型,然后在其上运行python脚本,为每个数据包生成原型结构和序列化/反序列化函数。
答案 4 :(得分:1)
这是一个“开箱即用”的解决方案,但我建议您查看Python construct库。
Construct是一个python库 解析和构建数据 结构(二进制或文本)。它是 基于定义数据的概念 结构以声明的方式, 而不是程序代码:更多 复杂结构由a组成 更简单的层次结构。就是这样 第一个使解析变得有趣的库, 而不是通常的头痛 今天。
构造非常强大和强大,只需阅读教程将帮助您更好地理解问题。作者还计划从定义中自动生成C代码,因此绝对值得花时间阅读。