我正在尝试实现一个简单的串口协议(protocol)。它是这样的:
- 丢弃所有数据,直到收到
0xff
- 读头(节点地址和数据长度,4字节)
- 读取数据(最大 64 字节)
- 阅读crc
- 处理接收到的数据包
- 发送回复
- 当看到
0xff
时,即使在数据中间不是预期的情况下,也意味着收到了一个新数据包
我可以使用 boost::asio::serial_port
和 boost::asio::read()
来实现这个已收到。虽然这行得通,但我想知道是否有更像“提升”的方法来做到这一点?
我查看了 boost::asio::read_until()
以读取直到 0xff
,但我不知道如何丢弃数据。将数据存储在缓冲区中然后不使用缓冲区似乎有点浪费。
我可以使用 boost::asio::read_until()
读取直到数据包结束,但是 MatchCondition
需要访问(的 header 缓冲区中的数据包。似乎 MatchCondition
只得到一个指向最近收到的第一个和最后一个字节的迭代器。
此外,使用 boost::asio::read()
接收的数据最终在 stream_buf
中,我必须将接收到的数据解析为 数据包
对象。我可以在 Packet
中,在一个单独的 ParsePacket
对象中进行解析,或者以某种方式将它与 boost::asio
集成(类似于 boost::asio::read(serial, myPacket);
其中 myPacket
是一个 Packet
对象)
当 0xff
在接收到的数据中的任何地方出现时,这意味着一个新的数据包正在开始。因此,当接收到 0xff
时,它必须忘记之前接收到的任何数据并开始接收新数据包。
我计划使用异步操作并添加超时。
所以,我的问题是:在哪里实现这样的协议(protocol)?或者更一般地说,在何处使用 boost::asio
实现协议(protocol)。我不是在寻找工作代码,而是在寻找在何处实现协议(protocol)以及要使用哪些 boost::asio
功能方面的建议。
更新:
在这种情况下没有使用流控制(硬件或软件)。
最佳答案
首先,正如@Autopulated 在评论中指出的那样,我想警告您在二进制协议(protocol)中使用定界符(您的 0xFF)。这是一种危险的技术(带来很多歧义)并且需要复杂的实现。即使您可以保证您的数据不包含 0xFF 字节,您也不能对 CRC 字段执行此操作。
我建议不要理会任何定界符,而是专注于简单且可预测的二进制协议(protocol):[packet][packet]...
其中[packet] = [node address:X ][数据长度:4][数据:数据长度][CRC:1]
发送这样的数据包看起来像:
size_t const data_length_bytes = 4;
std::vector<char> data = ...;
size_t data_length = data.size();
Node_address node_address = ...;
std::vector<boost::asio::const_buffer> bufs;
bufs.push_back(boost::asio::buffer(&node_address, sizeof(node_address)));
bufs.push_back(boost::asio::buffer(&data_length, data_length_bytes));
bufs.push_back(boost::asio::buffer(data));
boost::system::error_code error;
boost::asio::write(socket, boost::asio::buffer(bufs), error);
if (error)
throw boost::system::system_error(error);
接收:
size_t data_length;
std::vector<char> data;
Node_address node_address;
char crc;
std::vector<boost::asio::mutable_buffer> bufs;
boost::system::error_code error;
bufs.push_back(boost::asio::buffer(&node_address, sizeof(node_address)));
bufs.push_back(boost::asio::buffer(&data_length, data_length_bytes));
boost::asio::read(serial_port, bufs, error);
if (error)
throw boost::system::system_error(error);
data.resize(data_length);
bufs.clear();
bufs.push_back(boost::asio::buffer(&data.front(), data_length));
bufs.push_back(boost::asio::buffer(&crc, sizeof(crc));
boost::asio::read(serial_port, bufs, error);
if (error)
throw boost::system::system_error(error);
// check CRC
// send response
请注意,此示例假设两个对等方具有相同的字节顺序。
我在这里写了这段代码,所以不要指望它是正确的,只是作为一个想法使用它。
关于c++ - 在哪里使用 boost::asio 实现协议(protocol)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8178802/