C++ boost::asio::buffer:获取缓冲区大小并防止缓冲区溢出?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15060671/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
boost::asio::buffer: Getting the buffer size and preventing buffer overflow?
提问by pandoragami
I have the two following functions for sending and receiving packets.
我有以下两个用于发送和接收数据包的功能。
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";
}
The questions pertain to this part boost::asio::buffer(reply, request_length)
where the request length is the length of a string which was initially setup when the packet was sent. How do I check the size of the buffer without knowing request_length
? Another question is how do I prevent buffer overflow?
问题与这部分有关,boost::asio::buffer(reply, request_length)
其中请求长度是在发送数据包时最初设置的字符串的长度。如何在不知道的情况下检查缓冲区的大小request_length
?另一个问题是如何防止缓冲区溢出?
回答by Tanner Sansbury
To get the size of a buffer, the boost::asio::buffer_size()
function can be used. However, in your example, this will most likely be of little use to you.
要获取缓冲区的大小,boost::asio::buffer_size()
可以使用该函数。但是,在您的示例中,这很可能对您没什么用。
As explained in the buffer overview, Boost.Asio use buffer classes to represent buffers. These classes provide an abstraction and protect Boost.Asio operations against buffer overruns. Although the result of boost::asio::buffer()
is passed to operations, the meta-data, such as the size of the buffer or its underlying type, is not transmitted. Also, these buffers do not own the memory, so it is the applications responsibility to ensure the underlying memory remains valid throughout the duration of the buffer abstraction's lifetime.
正如缓冲区概述中所解释的,Boost.Asio 使用缓冲区类来表示缓冲区。这些类提供抽象并保护 Boost.Asio 操作免受缓冲区溢出。尽管将结果boost::asio::buffer()
传递给操作,但不会传输元数据,例如缓冲区的大小或其基础类型。此外,这些缓冲区不拥有内存,因此应用程序有责任确保底层内存在缓冲区抽象的整个生命周期内保持有效。
The boost::asio::buffer()
function provides a convenient way to create the buffer classes, where the size of the buffer is deduced from the type possible. When Boost.Asio is able to deduce the buffer length, then Boost.Asio operations will not invoke a buffer overflow when using the resulting buffer type. However, if the application code specifies the size of the buffer to boost::asio::buffer()
, then it is the applications responsibility to ensure that the size is not larger than the underlying memory.
该boost::asio::buffer()
函数提供了一种创建缓冲区类的便捷方法,其中缓冲区的大小是从可能的类型中推导出来的。当 Boost.Asio 能够推导出缓冲区长度时,Boost.Asio 操作在使用结果缓冲区类型时将不会调用缓冲区溢出。但是,如果应用程序代码将缓冲区的大小指定为boost::asio::buffer()
,则应用程序有责任确保该大小不大于底层内存。
When reading data, a buffer is required. The fundamental question becomes how does one know how much memory to allocate, if Boost.Asio does not transmit the size. There are a few solutions to this problem:
读取数据时,需要一个缓冲区。如果 Boost.Asio 不传输大小,那么基本问题就变成了如何知道要分配多少内存。这个问题有几个解决方案:
Query the socket for how much data is available via
socket::available()
, then allocate the buffer accordingly.std::vector<char> data(socket_.available()); boost::asio::read(socket_, boost::asio::buffer(data));
Use a class that Boost.Asio can grow in memory, such as
boost::asio::streambuf
. Some operations, such asboost::asio::read()
acceptstreambuf
objects as their buffer and will allocate memory as is required for the operation. However, a completion condition should be provided; otherwise, the operation will continue until the buffer is full.boost::asio::streambuf data; boost::asio::read(socket_, data, boost::asio::transfer_at_least(socket_.available()));
As ?? Tiibsuggests, incorporate length as part of the communication protocol. Check the Boost.Asio examplesfor examples of communication protocols. Focus on the protocol, not necessarily on the Boost.Asio API.
- In a fixed size protocol, both the data producer and consumer use the same size message. As the reader knows the size of the message, the reader can allocate a buffer in advance.
In a variable length protocol, the messages are often divided into two parts: a header and a body. The header is normally fixed size, and can contain various meta-information, such as the length of the body. This allows a reader to read a header into a fixed size buffer, extract the body length, allocate a buffer for the body, then read the body.
// 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.
通过 查询套接字可用的数据量
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示例以获取通信协议示例。专注于协议,不一定是 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.
回答by ?? Tiib
Typically a communication protocol either uses fixed length messages or messages that contain header that tells the length of message.
通常,通信协议要么使用固定长度的消息,要么使用包含指示消息长度的标头的消息。
Boost.Asio online documentationcontains large set of examples and tutorials so you should perhaps start from there. Wikipedia is good source for explaining data transmissionterminology, boost asio documentation does not do it.
Boost.Asio 在线文档包含大量示例和教程,因此您或许应该从那里开始。维基百科是解释数据传输术语的好来源,boost asio 文档没有这样做。
回答by perreal
I think your question is confusing, but this might help:
我认为您的问题令人困惑,但这可能会有所帮助:
void receive() {
enum { max_length = 1024 };
char reply[max_length];
size_t reply_length;
std::cout << "Reply is: ";
while ( (reply_length = ba::read(s, basio::buffer(reply, max_length))) > 0) {
std::cout.write(reply, reply_length);
}
std::cout << "\n";
}