c – boost :: asio :: buffer:获取缓冲区大小并防止缓冲区溢出?
作者:互联网
我有以下两个用于发送和接收数据包的功能.
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()的结果被传递给操作,但是不传输元数据,例如缓冲区的大小或其底层类型.此外,这些缓冲区不拥有内存,因此应用程序有责任确保底层内存在缓冲区抽象的生命周期内保持有效.
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()
)接受streambuf对象作为其缓冲区,并将按操作所需的内容分配内存.但是,应提供完成条件;否则,操作将继续,直到缓冲区已满.
boost::asio::streambuf data;
boost::asio::read(socket_, data,
boost::asio::transfer_at_least(socket_.available()));
>正如Öö Tiib所示,将长度作为通信协议的一部分.有关通信协议的示例,请查看Boost.Asio examples.专注于协议,不一定在Boost.Asio API上.
>在固定大小的协议中,数据生产者和消费者都使用相同大小的消息.当读者知道消息的大小时,读者可以提前分配缓冲区.
>在可变长度协议中,消息通常分为两部分:标题和正文.标题通常是固定大小,并且可以包含各种元信息,例如正文的长度.这允许读者将标题读入固定大小的缓冲区,提取体长,为身体分配缓冲区,然后读取体.
// 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.
标签:buffer-overflow,c,boost-asio 来源: https://codeday.me/bug/20191004/1853284.html