【问题标题】:Sending Packet objects with boost asio使用 boost asio 发送 Packet 对象
【发布时间】:2021-07-16 14:20:43
【问题描述】:

采取以下措施:

struct Header{
    std::size_t body_size;
};
struct Body{
    std::string data;
};
struct Packet{
    Header header;
    Body body;


};

现在假设我想通过tcp 套接字发送Packet 对象。

为此,我想将标头序列化为std::string,其中包含有关body 大小的信息,并通过套接字发送string

但是这个序列化的标头字符串本身具有可变大小,因为body_size 不固定,所以我怎么知道要读取多少字节(序列化标头字符串)

那么在发送这样的数据时使用了什么样的协议呢?

【问题讨论】:

  • 对于简单的数据,您可以序列化为 JSON,或使用像 CBOR 这样的二进制格式,或者如果您准备迎接挑战,请使用 Google Protocol Buffers 定义您自己的数据格式
  • 使您的协议的每一帧都采用[size data] 的形式。首先读取大小,然后读取数据包的其余部分。这可能不是最好的方法,但它可以在面向流的套接字中工作。
  • 您是否有理由希望将标头作为字符串发送? TCP 是一个字节流,所以你可以直接发送size_t

标签: c++ boost asio


【解决方案1】:

最常用的通过TCP 套接字发送数据的协议是HTTP
HTTP 中,正文大小作为相关标头[请求、响应或块] 中的字符串发送,带有特殊字符(\r\n 用于请求或响应,; 用于块)以标识大小字符串。
您需要决定自己的特殊角色; NULL 将是最简单的空终止字符串。

按照您的建议发送数据的一个关键问题是,TCP 可以将数据拆分为多个(通常所说的)packets,因此接收方可能不会收到您的全部@ 987654335@一次。
顺便说一句,Packet 在这种情况下是一个糟糕的名字。

在发送之前,您无需知道完整的Packet 的大小。您可以使用 const_buffers 的集合调用 boost:asio async_write 来发送您的 PacketHeaderBody

在接收端,我建议使用async_read_some 和一个足够大的string 缓冲区,以容纳整个Packet,包括Header 字符串。
您应该能够从NULL 之前的字符中读取Body 的大小,并根据Body 的大小加上NULL + 1 之前的字符数计算您的Packet 大小(对于NULL )。如果这小于您的ReadHandler 报告的大小,那么您的Body 已被拆分为多个TCP packets,因此您需要接收另一个packets 来重建您的Packet @987654356 @。

或者,您可以省去麻烦,只需使用经过验证的HTTP 库,例如via-httplibboost::beast

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多