Boost :: asio read n bytes from socket in streambuf

I have a serialized structure that is sent through a socket. I need to read it in chunks, since one of its fields contains the size of the remaining data, so I need to read the first few bytes, find out the length and read the rest. This is what I have:

boost::asio::streambuf buffer; boost::system::error_code err_code; // here I need to read only first 16 bytes boost::asio::read(socket, buffer, err_code); std::istream is(&buffer); boost::archive::binary_iarchive ia(is); ia >> my_struct; 

I looked at

  boost::asio::async_read(s, boost::asio::buffer(data, size), handler); 

but it can only read data for boost :: asio :: buffer. I am wondering if I can do the same with boost :: asio :: streambuf? Thank you in advance.

+5
source share
1 answer

There are overloads for boost::asio::read() and boost::asio::async_read() that accept instances of boost::asio::basic_streambuf as their buffer:

 read(SyncReadStream&, basic_streambuf&); read(SyncReadStream&, basic_streambuf&, CompletionCondition); read(SyncReadStream&, basic_streambuf&, boost::system::error_code&); read(SyncReadStream&, basic_streambuf&, CompletionCondition, boost::system::error_code&); async_read(AsyncReadStream&, basic_streambuf&, ReadHandler); async_read(AsyncReadStream&, basic_streambuf&, CompletionCondition, ReadHandler); 

When invoking an overload that does not take the value of CompletionCondition, this is the equivalent of invoking the associated overload using CompletionCondition boost::asio::transfer_all() , as a result of which the operation is read streambuf.max_size() .


To read the known number of bytes in streambuf use:

  • boost::asio::transfer_exactly(n) CompletionCondition to limit the number of bytes transferred from a folded operation:

     std::size_t n = // ... boost::asio::read(socket, streambuf, boost::asio::transfer_exactly(n), error); 
  • Explicitly creating an output sequence that will serve as a buffer, after which the bytes are read into the input sequence streambuf:

     std::size_t n = // ... std::size_t bytes_transferred = boost::asio::read(socket, streambuf.prepare(n), // creates a boost::asio::buffer error); streambuf.commit(bytes_transferred); 

Here is a complete example of a demonstration of both of these approaches:

 #include <iostream> #include <boost/asio.hpp> #include <boost/bind.hpp> // This example is not interested in the handlers, so provide a noop function // that will be passed to bind to meet the handler concept requirements. void noop() {} std::string make_string(boost::asio::streambuf& streambuf) { return {boost::asio::buffers_begin(streambuf.data()), boost::asio::buffers_end(streambuf.data())}; } int main() { using boost::asio::ip::tcp; boost::asio::io_service io_service; // Create all I/O objects. tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 0)); tcp::socket server_socket(io_service); tcp::socket client_socket(io_service); // Connect client and server sockets. acceptor.async_accept(server_socket, boost::bind(&noop)); client_socket.async_connect(acceptor.local_endpoint(), boost::bind(&noop)); io_service.run(); // Write to server. boost::asio::streambuf write_buffer; std::ostream output(&write_buffer); output << "abc"; std::cout << "Writing: " << make_string(write_buffer) << std::endl; auto bytes_transferred = boost::asio::write(server_socket, write_buffer); // Read from client. boost::asio::streambuf read_buffer; bytes_transferred = boost::asio::read(client_socket, read_buffer, boost::asio::transfer_exactly(bytes_transferred)); std::cout << "Read: " << make_string(read_buffer) << std::endl; read_buffer.consume(bytes_transferred); // Remove data that was read. // Write to server. output << "def"; std::cout << "Writing: " << make_string(write_buffer) << std::endl; bytes_transferred = boost::asio::write(server_socket, write_buffer); // Read from client. bytes_transferred = boost::asio::read(client_socket, read_buffer.prepare(bytes_transferred)); read_buffer.commit(bytes_transferred); std::cout << "Read: " << make_string(read_buffer) << std::endl; read_buffer.consume(bytes_transferred); // Remove data that was read. } 

Conclusion:

 Writing: abc Read: abc Writing: def Read: def 
+14
source

Source: https://habr.com/ru/post/1214941/


All Articles