Boost :: asio :: buffer: getting buffer size and preventing buffer overflow?

I have the following two 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"; } 

Questions relate to this part of boost::asio::buffer(reply, request_length) , where the request length is the length of the string that was originally configured when the packet was sent. How to check buffer size without knowing request_length ? Another question: how to prevent buffer overflows?

+6
source share
3 answers

To get the size of the buffer, you can use the boost::asio::buffer_size() function. However, in your example, this is likely to be of little use to you.

As explained in the overview buffer, Boost.Asio uses buffer classes to represent buffers. These classes provide abstraction and protect Boost.Asio operations from buffer overflows. Although the result of boost::asio::buffer() is passed to operations, metadata, such as the size of the buffer or its base type, is not passed. In addition, these buffers do not own memory, so the responsibility for applications lies in ensuring that the underlying memory remains valid throughout the life of the buffer abstraction.

The boost::asio::buffer() function provides a convenient way to create buffer classes where the buffer size is inferred from a possible type. When Boost.Asio is able to output the length of the buffer, Boost.Asio operations will not cause buffer overflows when using the resulting buffer type. However, if the application code indicates the buffer size to boost::asio::buffer() , then the responsibility for the application must ensure that the size does not exceed the base memory.

When reading data, a buffer is required. The main question is how to find out how much memory is allocated if Boost.Asio does not transmit the size. There are several solutions to this problem:

  • Request a socket about how much data is available through socket::available() , then apportion 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, like boost::asio::streambuf . Some operations, such as boost::asio::read() take streambuf objects as their buffer and allocate the memory needed for the operation. However, a termination condition must 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())); 
  • How Γ–ΓΆ Tiib suggests including length as part of a communication protocol. For example communication protocols, check Boost.Asio examples . Focus on the protocol, not necessarily the Boost.Asio API.

    • In a fixed-size protocol, both the data producer and the consumer use the same message. Since the reader knows the size of the message, the reader can preallocate a buffer.
    • In a variable-length protocol, messages are often divided into two parts: the header and the body. The header is usually a fixed size and may contain various meta-information, such as body length. This allows the reader to read the header into a fixed-size buffer, extract the length of the body, allocate a buffer for the body, and 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. 
+15
source

Typically, a communication protocol uses fixed-length messages or messages containing a header that reports the length of the message.

The online documentation of Boost.Asio contains a wide range of examples and tutorials, so you should start from now on. Wikipedia is a good source for explaining data transfer ; boost asio terminology does not.

+5
source

I think your question is confusing, but this may 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"; } 
+1
source

All Articles