首页 > 解决方案 > 如何处理许多不同的输入二进制消息类型

问题描述

我有一个设备,我通过发送和接收特定的二进制数据包结构与之通信。该设备有一个定义良好的 API,但它可以返回 100 多种可能的消息类型。用于处理这些不同消息类型的良好设计是什么?

这是一个伪代码示例,我忽略了框架和校验和字节以使其更清晰。

// I receive this message, where 0x00 indicates the device status,
//and each other byte is a particular error or status
message = [0x00, 0x01, 0x01, 0x04]
// The next message I receive, where 0x10 indicates system time, 
// and the rest of the fields are the integer clock seconds of the device.
message = [0x10, 0x00, 0x32, 0xFF, 0x8E]
// 100 other message types....

如您所见,我收到的每条消息都需要进行略微不同的处理,具有不同的含义。我原本打算使用一个巨大的 switch 语句case 0x00: process_errors() case 0x10: process_time(),但我很好奇是否有更好的设计可以用来增加添加新消息类型的灵活性、更好的可用性等。

标签: c++design-patternsio

解决方案


您可以尝试使用 TLV(标签长度值)实现。它适用于处理数据流。

标签- 这将是一个数据字节(根据您的示例),用于标识随后的消息类型。要使用此功能,您应该事先了解哪种消息类型具有多少数据。例如,在 0x00(设备状态)的情况下,您现在应该预先知道接下来的 3 个字节是数据。

长度- 数据字节的长度

- 实际数据

以下是您可以执行的操作:
1) 准备您的系统支持的不同消息的标签和长度的映射。
2) 连续接收字节数据。
3)读取第一个字节(这将是标签)并确定它是什么类型的消息。在您的情况下,这将为您提供 0x00、0x10 等。
4) 请参阅您的标签和长度信息图。您将确定需要进一步读取的数据字节数。
5)一旦你读取了数据部分,你的接收器应该准备好接收下一条消息(准备读取下一个标签)

这都是关于阅读消息的。获得消息及其数据后,您可以随意使用它。例如,除了标签对应的消息长度之外,您还可以注册一个函数。这将允许您调用特定函数及其所需的参数。

设备状态

Data Tag = 00  
Data Length = 03  
Data Value =  01 01 04 

系统时间

Data Tag = 10  
Data Length = 04  
Data Value =  00 32 FF 8E  

推荐阅读