How can I get the data inside a beast::flat_buffer?

3.9k Views Asked by At

I'm connecting to a websocket using the boost/beast libraries and writing the data into a beast::flat_buffer. My issue is that I'm having trouble getting the data from buffer. I have a thread-safe channel object that I can to write to, but I'm not sure how to pull the most recently received message from the buffer.

beast::flat_buffer buffer;
// send through socket
send_socket(
   ws, get_subscribe_string(trade_tickers, bar_tickers, quote_tickers));
// read into buffer
while (channel.running) {
   ws.read(buffer); // need to write the most recently received message into the channel
}

I can write to the channel with channel.write(std::string arg). Any ideas on how to pull from the buffer?

1

There are 1 best solutions below

0
On BEST ANSWER

The interface for flat_buffer is documented here: https://www.boost.org/doc/libs/1_77_0/libs/beast/doc/html/beast/ref/boost__beast__flat_buffer.html

As you can see it is a rich interface that lends itself to a number of different usage patterns, including reading and writing blocks in FIFO style.

Now, if you are using websockets, your protocol is already message-oriented rather than stream oriented. You might just want to access all of the data as one "body". In my opinion, the safe, expressive and flexible way to do this is using the data() member. This models the general Asio Buffer concept meaning that you can use the Buffer Iterators on it, without worrying about any of the buffer implementation details:

std::string text(buffers_begin(buffer), buffers_end(buffer));

For an example of this in actual use (to receive JSON or msgpack) see this recent answer: I would like to parse a boost::beast::flat_buffer with msgpack data using nlohmann:json

Think Outside The Box

Note the implication though: The flat_buffer is not mandatory. In fact, it's just one (simple) implementation modeling the DynamicBuffer concept.

You could use any model, so instead you can receive directly into a string:

std::string str;

auto buf = boost::asio::dynamic_buffer(str);
ws.read(str);

If you reuse str instance, e.g. just using str.clear() it may not be bad in terms of allocations.