The Beast websocket example stores the data in a multibuffer:
The implementation uses a sequence of one or more character arrays of varying sizes. Additional character array objects are appended to the sequence to accommodate changes in the size of the character sequence.
When looking at the interface it is not completely clear to me how it works. If I read the descriptions it can be seen as an array of buffers. But it seems the output is only a single chunk of data. Does this mean the "one or more arrays" are only applicable to the internal structure ?
In the example code the data is read into the buffer as follows: m_websocketStream.async_read(m_buffer.....
Does each async_read operation creates a new internal buffer.
If this is the case, how to interpret it at the other end. E.G. how to read it into a std::string or std::vector.
When looking into the sources data() returns const_buffer_type, which is a forward declaration.
For the data member the help information provides the following info, which is not of much help:
The type used to represent the input sequence as a list of buffers. using const_buffers_type = implementation_defined;
The definition seems to come from the header file boost/asio/buffer.hpp which is included as well. The overall structure however is somewhat obfuscating to me.
I just try to understand how to handle the data as bytes or convert it to as std::string.
Tried the following, but this is also not allowed:
std::string( boost::asio::buffer_cast<const char*>(m_buffer.data())
,boost::asio::buffer_size(m_buffer.data()) );
Anyone who can enlighten me a little ?
data()
returns an object meeting the requirements of ConstBufferSequence (http://www.boost.org/doc/libs/1_65_0/doc/html/boost_asio/reference/ConstBufferSequence.html). prepare()
returns an object meeting the requirements of MutableBufferSequence (http://www.boost.org/doc/libs/1_65_0/doc/html/boost_asio/reference/MutableBufferSequence.html)
All of the dynamic buffers in beast meet the requirements of DynamicBuffer, described in http://www.boost.org/doc/libs/develop/libs/beast/doc/html/beast/concepts/DynamicBuffer.html
If you want to convert a buffer sequence into a string you need to loop over each element and append it to the string individually. Such a function might look like this:
template<class ConstBufferSequence>
std::string
to_string(ConstBufferSequence const& buffers)
{
std::string s;
s.reserve(boost::asio::buffer_size(buffers));
for(boost::asio::const_buffer b : buffers)
s.append(boost::asio::buffer_cast<char const*>(b),
boost::asio::buffer_size(b));
return s;
}
Alternatively, if you want to avoid the buffer copy you can use something like beast::flat_buffer
which guarantees that all the buffer sequences will have length one. Something like this:
inline
std::string
to_string(beast::flat_buffer const& buffer)
{
return std::string(boost::asio::buffer_cast<char const*>(
beast::buffers_front(buffer.data())),
boost::asio::buffer_size(buffer.data()));
}
For more information on buffers, see http://www.boost.org/doc/libs/1_65_0/doc/html/boost_asio/overview/core/buffers.html
In the latest versions of Beast, there is now the function buffers_to_string
which will do this for you in a single function call.
来源:https://stackoverflow.com/questions/46132570/trying-to-understand-the-boostbeast-multibuffer