我有以下两个用于发送和接收数据包的函数。
void send(std::string protocol)
{
char *request=new char[protocol.size()+1];
request[protocol.size()] = 0;
memcpy(request,protocol.c_str(),protocol.size());
request_length = std::strlen(request);
boost::asio::write(s, boost::asio::buffer(request, request_length));
}
void receive()
{
char reply[max_length];
size_t reply_length = boost::asio::read(s, boost::asio::buffer(reply, request_length));
std::cout << "Reply is: ";
std::cout.write(reply, reply_length);
std::cout << "\n";
}
与这部分相关的问题boost::asio::buffer(reply, request_length)
其中请求长度是发送数据包时最初设置的字符串的长度。如何在不知道的情况下检查缓冲区的大小request_length
?另一个问题是如何防止缓冲区溢出?
要获取缓冲区的大小,boost::asio::buffer_size()可以使用函数。但是,在您的示例中,这很可能对您没什么用处。
正如缓冲区中所解释的overview、Boost.Asio使用缓冲区类来表示缓冲区。这些类提供了抽象并保护 Boost.Asio 操作免遭缓冲区溢出。虽然结果boost::asio::buffer()
传递给操作时,不会传输元数据,例如缓冲区的大小或其基础类型。此外,这些缓冲区不拥有内存,因此应用程序有责任确保底层内存在缓冲区抽象的整个生命周期内保持有效。
The boost::asio::buffer()
函数提供了一种创建缓冲区类的便捷方法,其中缓冲区的大小是从可能的类型推导出来的。当 Boost.Asio 能够推断出缓冲区长度时,Boost.Asio 操作在使用生成的缓冲区类型时将不会引发缓冲区溢出。但是,如果应用程序代码指定缓冲区的大小boost::asio::buffer()
,那么应用程序有责任确保该大小不大于底层内存。
读取数据时,需要缓冲区。根本问题是,如果 Boost.Asio 不传输大小,如何知道要分配多少内存。这个问题有几个解决方案:
-
通过以下方式查询套接字有多少数据可用socket::available(),然后相应地分配缓冲区。
std::vector<char> data(socket_.available());
boost::asio::read(socket_, boost::asio::buffer(data));
-
使用Boost.Asio可以在内存中增长的类,例如boost::asio::streambuf。一些操作,例如boost::asio::read() accept streambuf
对象作为其缓冲区,并将根据操作所需分配内存。但应提供完成条件;否则,操作将继续,直到缓冲区已满。
boost::asio::streambuf data;
boost::asio::read(socket_, data,
boost::asio::transfer_at_least(socket_.available()));
-
As Öö Tiib建议将长度作为通信协议的一部分。检查Boost.Asioexamples有关通信协议的示例。关注协议,不一定关注Boost.AsioAPI.
- 在固定大小的协议中,数据生产者和消费者都使用相同大小的消息。由于阅读器知道消息的大小,因此阅读器可以提前分配缓冲区。
-
在可变长度协议中,消息通常分为两部分:标头和主体。标头通常是固定大小的,并且可以包含各种元信息,例如主体的长度。这允许读取器将标头读入固定大小的缓冲区,提取主体长度,为主体分配缓冲区,然后读取主体。
// Read fixed header.
std::vector<char> data(fixed_header_size);
boost::asio::read(socket_, boost::asio::buffer(data));
protocol::header header(data);
network_to_local(header); // Handle endianess.
// Read body.
data.resize(header.body_length());
boost::asio::read(socket_, boost::asio::buffer(data));
protocol::body body(data);
network_to_local(body); // Handle endianess.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)