gpt4 book ai didi

c++ - 在 C++ 中实现固定字节串行协议(protocol)的最佳实践?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:03:56 25 4
gpt4 key购买 nike

我有一个设备通过串行接口(interface)连接到 BeagleBone 计算机。我以简单的二进制格式进行通信,例如

|MessagID (1 Byte) | Data (n Bytes) | checksum (2 bytes) |

每个命令的消息长度是固定的,这意味着在收到命令的第一个字节后,知道要读取多少字节。经过一些初始设置通信后,它每 20 毫秒发送一次数据包。

我的方法是使用 termios 或类似 serial lib 的东西,然后开始一个循环(a:

while(keepRunning)
{
char* buffer[256];
serial.read(buffer, 1)
switch(buffer[0])
{
case COMMAND1:
serial.read(&buffer[1], sizeof(MessageHello)+2); //Read data + checksum
if (calculateChecksum(buffer, sizeof(MessageHello)+3) )
{
extractDatafromCommand(buffer);
}
else
{
doSomeErrorHandling(buffer[0]);
}
break;
case COMMAND2:
serial.read(&buffer[1], sizeof(MessageFoo)+2);
[...]
}
}

extractDatafromCommand 然后会创建一些结构,例如:

struct MessageHello
{
char name[20];
int version;
}

将所有内容放在自己的读取线程中,并使用信号量(或简单标志)向程序的其他部分发出新数据包可用性的信号。

这是一个可行的解决方案还是有更好的改进(我认为是)?

也许创建一个抽象类 Message 并派生其他消息?

最佳答案

这真的取决于。两种主要方式是线程化(如您提到的)和事件化。

线程代码很棘手,因为您很容易引入竞争条件。您测试过一百万次的代码在工作数天、数周或数年后偶尔会出错并做错事。很难“证明”事情总是会正确运行。像“i++”这样看似微不足道的东西突然变成了漏洞百出的抽象。 (参见 why is i++ not thread safe on a single core machine?)

另一种选择是事件编程。基本上,您有一个对所有文件句柄执行 select() 的主循环。任何准备就绪的东西都会被查看,并且您尝试在不阻塞的情况下读取/写入尽可能多的字节。 (通过 O_NONBLOCK)。有两个棘手的部分:1)你绝不能在没有办法返回主循环的情况下进行长时间的计算,以及 2)你绝不能进行阻塞操作(内核停止你的进程等待读取或写入) .

在实践中,大多数程序都不会进行长时间的计算,并且审计少量代码以阻止调用比竞争更容易。 (虽然在不阻塞的情况下执行 DNS 比它应该的更棘手。)

事件代码的优点是不需要锁定(无需担心其他线程)并且浪费更少的内存(在创建大量线程的一般情况下。)

您很可能想使用串行库。 termios 处理只是开销和杂散字节做坏事的机会。

关于c++ - 在 C++ 中实现固定字节串行协议(protocol)的最佳实践?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16181462/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com