c++ - 在哪里使用 boost::asio 实现协议(protocol)?

标签 c++ protocols boost-asio

我正在尝试实现一个简单的串口协议(protocol)。它是这样的:

  1. 丢弃所有数据,直到收到 0xff
  2. 读头(节点地址和数据长度,4字节)
  3. 读取数据(最大 64 字节)
  4. 阅读crc
  5. 处理接收到的数据包
  6. 发送回复
  7. 当看到 0xff 时,即使在数据中间不是预期的情况下,也意味着收到了一个新数据包

我可以使用 boost::asio::serial_portboost::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/

相关文章:

c++ - boost::asio::ip::multicast::join_group 不起作用

c++ - boost::asio async_read_some async_read_until 编译器警告

c++ - 对于 C++,是否有两次从控制台中的 txt 文件重定向(cin)输入?

c++ - 为了便于阅读,在 GDB 上缩写 C++ 模板?

C++ 非阻塞 ASIO 运行

database - 遵守数据模型协议(protocol)的优势

serial-port - DTR/DSR 和 RTS/CTS 流量控制有什么区别?

c++ - 使用 LoadImage() 中的 GetObjet() 后,BITMAP 结构中的 bmBit 始终为 NULL

C++ MFC : Debug Assertion error when trying to call method using instance of a class

outlook - Outlook 支持哪些协议(protocol)进行双向日历同步?