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
创建的缓冲区一个一个地添加到这个向量中。
我正在学习如何使用 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
创建的缓冲区一个一个地添加到这个向量中。