Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/130.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+中实现固定字节串行协议的最佳实践+;?_C++_Linux_Serial Port_Protocols - Fatal编程技术网

C++ 在C+中实现固定字节串行协议的最佳实践+;?

C++ 在C+中实现固定字节串行协议的最佳实践+;?,c++,linux,serial-port,protocols,C++,Linux,Serial Port,Protocols,我有一个通过串行接口连接到BeagleBone计算机的设备。我用一种简单的二进制格式进行通信,如 |MessagID (1 Byte) | Data (n Bytes) | checksum (2 bytes) | 每个命令的消息长度是固定的,这意味着在接收到命令的第一个字节后,就知道要读取多少字节。在一些初始设置通信之后,它每20毫秒发送数据包 我的方法是使用termios或类似于serial lib的东西,然后启动一个这样的循环(a: 然后,extractDatafromCommand将创

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

|MessagID (1 Byte) | Data (n Bytes) | checksum (2 bytes) |
每个命令的消息长度是固定的,这意味着在接收到命令的第一个字节后,就知道要读取多少字节。在一些初始设置通信之后,它每20毫秒发送数据包

我的方法是使用termios或类似于serial lib的东西,然后启动一个这样的循环(a:

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

struct MessageHello
{
    char name[20];
    int version;
}
将所有内容放在自己的读取线程中,并使用信号量(或简单标志)向程序的其他部分发出新数据包可用性的信号

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


可能生成一个抽象类消息并派生其他消息?

这取决于具体情况。这两种主要方式是线程化(如您所述)和事件化

线程化代码很棘手,因为你可以很容易地引入竞争条件。经过数百万次测试的代码在工作了几天、几周或几年后,偶尔会出错。很难“证明”事情总是正确的。像“i++”这样看似琐碎的东西突然变成了漏洞百出的抽象。(请参阅)

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

在实践中,大多数程序的计算时间都不长,审计少量代码以阻止调用比审核竞争更容易。(虽然在没有阻塞的情况下进行DNS比应该的要复杂。)

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


最有可能的情况是,您希望使用串行库。termios处理只是一种开销,而且可能会让多余的字节做坏事。

这要看情况而定。这两种主要方式是线程化(如您所提到的)和事件化

线程化代码很棘手,因为您可以很容易地引入竞争条件。您测试了一百万次的代码在工作了几天、几周或几年后可能偶尔会出错。很难“证明”事情总是正确的。像“i++”这样看似琐碎的东西突然变成了漏洞百出的抽象。(见附件)

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

在实践中,大多数程序的计算时间都不长,审计少量代码以阻止调用比审核竞争更容易。(虽然在没有阻塞的情况下进行DNS比应该的要复杂。)

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


最有可能的情况是,您希望使用串行库。termios处理只会增加开销,而且会让多余的字节做坏事。

您可以添加一个退出while循环的命令,这在某些情况下可能很有用。我认为使用该读取线程是一个好主意。最好不要阻塞命令。一些错误恢复机制也很有用。您可以为每条消息定义一个结构,然后使用sizeof()而不是硬编码常量。您的程序似乎假定接收到的第一个字节是消息帧的第一个字节。在读取消息时,此帧同步将保持不变。如果串行字符丢失,所有这些都会中断。查找并维护消息帧对于健壮的串行通信协议至关重要。消息ID和2个校验和字节可能是查找可变长度消息帧的挑战。您可能需要添加一个固定值同步字节,以简化对消息帧开头的搜索。“固定字节”会产生误导。您有可变长度的消息。长度是从messageID派生/推导的,而不是显式存储在消息中,这只是一个小细节。与固定长度的消息相比,对于可变长度的消息来说,搜索消息帧的开头更难。如果您的USART具有“接收器超时”功能,则可以使用该计时器帮助检测单个消息帧(即消息之间的20毫秒)。但是检测消息之间的时间间隔必须由硬件而不是软件来完成。您可以添加一个退出while循环的命令,这在某些情况下可能很有用。我认为使用该读取线程是一个好主意。最好不要阻塞命令。一些错误恢复机制也很有用。您可以为每条消息定义一个结构,然后使用sizeof()而不是硬编码常量。您的程序似乎假定接收到的第一个字节是消息帧的第一个字节。在读取消息时,此帧同步将保持不变。如果串行字符丢失,所有这些都会中断。查找并维护消息帧对于健壮的串行通信协议至关重要。一个消息ID和2个校验和字节可能是查找可变长度混乱的挑战
struct MessageHello
{
    char name[20];
    int version;
}