boost::asio read n bytes from socket to streambuf

前端 未结 1 506
不知归路
不知归路 2020-12-23 23:35

I have a serialized structure, which is being sent via socket. I need to read it in chunks, since one of its fields contains the size of the data remaining: I need to read f

相关标签:
1条回答
  • 2020-12-24 00:20

    There are overloads for both boost::asio::read() and boost::asio::async_read() that accept instances of boost::asio::basic_streambuf as its 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 calling an overload that does not accept a CompletionCondition, it is the equivalent to calling its associated overload with a CompletionCondition of boost::asio::transfer_all(), causing the operation to read streambuf.max_size() bytes.


    For reading a known amount of bytes into a streambuf, either use:

    • the boost::asio::transfer_exactly(n) CompletionCondition to limit the amount of bytes transferred from the composed 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 the buffer, then commiting the bytes read into the streambuf's input sequence:

      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 demonstrating 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.
    }
    

    Output:

    Writing: abc
    Read: abc
    Writing: def
    Read: def
    
    0 讨论(0)
提交回复
热议问题