boost::asio 使用包含字符串的 boost::array 构建缓冲区

boost::asio building a buffer with a boost::array containing strings

我正在学习如何使用 boost::asio,方法是遵循文档中的示例并对其进行扩展。 示例 Daytime.4 and Daytime.5 展示了如何实现同步 udp 服务器-客户端通信。该示例通过构造一个 char 类型的 boost 数组然后从该数组构造一个 boost 缓冲区来发送数据:

boost::array<char, 1> send_buf  = {{ 0 }};
socket.send_to(boost::asio::buffer(send_buf), receiver_endpoint);

还有一个例子,他们采用 std::string 并将其直接传递给缓冲区构造函数:

std::string message = make_daytime_string();
boost::system::error_code ignored_error;
socket.send_to(boost::asio::buffer(message),
remote_endpoint, 0, ignored_error);

到目前为止一切顺利。我现在尝试填充一个字符串数组并将该数组发送到我的 udp 服务器。这总是导致服务器在实际消息之前接收到垃圾字符。 当我像这样构造发送缓冲区时:

std::string message = "I am still here";
boost::array<std::string, 1> send_buf2  = {{ message}};
socket.send_to(boost::asio::buffer(send_buf2), receiver_endpoint);

我得到这样的输出: |��I am still here 当我的数组构造成这样时:

boost::array<std::string, 1> send_buf2  = {{ "I am still here" }};

我的输出中只有内存垃圾字符。两种情况下的接收长度均为 32(字符)。

服务器读取消息是这样的:

boost::array<char, 128> recv_buf;
size_t got = socket.receive_from(boost::asio::buffer(recv_buf),
                            remote_endpoint, 0, error);
std::string incoming(recv_buf.begin(), recv_buf.begin() + got);

这是构造发送缓冲区的一种糟糕方法还是有解决此问题的方法?

您调用了 buffer 函数的以下重载:

template<
    typename PodType,
    std::size_t N>
mutable_buffer buffer(
    boost::array< PodType, N > & data);

仅适用于 POD。 string 不是 POD 类型。

boost asio 中的缓冲区可以被视为一对:指向数据的指针和数据的长度。在您的情况下,您创建的缓冲区指向字符串的二进制表示,而不是它管理的数据 - std::string 的内部指针指向的字符序列(当使用小字符串优化时,此输出 |��I am still here 是可能的) .这解释了为什么你得到 32 个字节,它只是 sizeof(std::string) 用于你的库实现。

如果要发送由boost::array字符串管理的数据,可以使用复合缓冲区:

const boost::array<std::string,2> a{{"I am still here", "xxx"}};
std::vector<boost::asio::const_buffers_1> v;
v.push_back(boost::asio::buffer(a[0]));
v.push_back(boost::asio::buffer(a[1]));

创建缓冲区向量,并将基于std::string创建的缓冲区一个一个地添加到这个向量中。