gpt4 book ai didi

c++ - boost asio在基于tcp的协议(protocol)中找到消息的开头

转载 作者:行者123 更新时间:2023-11-30 05:11:01 25 4
gpt4 key购买 nike

我想为通过 tcp 发送数据并使用以下协议(protocol)的传感器实现客户端:

  1. 消息头以 uint32 类型的字节序列 0xAFFEC0CC2 开头
  2. header 总共有 24 个字节长(包括起始序列),并且包含以字节为单位的消息正文大小作为 uint32
  3. 消息正文直接在消息头之后发送,不以分界符终止

目前,我得到以下代码(假设存在连接的套接字)

typedef unsigned char byte;

boost::system::error_code error;
boost::asio::streambuf buf;
std::string magic_word_s = {static_cast<char>(0xAF), static_cast<char>(0xFE),
static_cast<char>(0xC0), static_cast<char>(0xC2)};

ssize_t n = boost::asio::read_until(socket_, buf, magic_word_s, error);
if(error)
std::cerr << boost::system::system_error(error).what() << std::endl;
buf.consume(n);
n = boost::asio::read(socket_, buf, boost::asio::transfer_exactly(20);

const byte * p = boost::asio::buffer_cast<const byte>(buf.data());
uint32_t size_of_body = *((byte*)p);

不幸的是documentation for read_until备注:

After a successful read_until operation, the streambuf may contain additional data beyond the delimiter. An application will typically leave that data in the streambuf for a subsequent read_until operation to examine.

这意味着我失去了与所描述协议(protocol)的同步。有什么优雅的方法可以解决这个问题吗?

最佳答案

好吧......正如它所说......你只需将它“留在”对象中,或者将它临时存储在另一个对象中,并在完整的情况下处理整个消息(下面称为“数据包”)。

我在我的一个项目中采用了类似的方法。我将稍微解释一下我是如何做到的,这应该能让您大致了解如何正确处理数据包。

在我的 Read-Handler (-callback) 中,我不断检查数据包是否完整。元数据信息(您的 header )临时存储在与远程合作伙伴关联的 map 中 (map )。

例如它可以是这样的:

4 byte identifier
4 byte message-length
n byte message

处理传入的数据,检查是否已经接收到标识符+消息长度,继续检查消息数据是否与接收到的数据一起完成。
将剩余的数据包留在临时缓冲区中,删除旧数据。
下一个数据包到达时继续处理或检查接收到的数据是否已经完成下一个数据包......

这种方法可能听起来有点慢,但我在一台速度较慢的机器上使用 SSL 10MB/s+ 时甚至可以达到。
如果没有 SSL,则可以实现更高的传输速率。

通过这种方法,您还可以查看 read_some或其 asynchronous版本。

关于c++ - boost asio在基于tcp的协议(protocol)中找到消息的开头,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45325491/

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