【问题标题】:boost::asio read n bytes from socket to streambufboost::asio 从 socket 读取 n 个字节到 streambuf
【发布时间】:2015-05-09 21:11:13
【问题描述】:

我有一个序列化的结构,它是通过套接字发送的。我需要分块读取它,因为它的一个字段包含剩余数据的大小:我需要读取前几个字节,找出长度并读取其余部分。这就是我得到的:

    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;

我看过

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

但它只能读取数据到 boost::asio::buffer。我想知道我是否可以对 boost::asio::streambuf 做同样的事情?提前谢谢你。

【问题讨论】:

    标签: c++ boost boost-asio boost-serialization streambuf


    【解决方案1】:

    boost::asio::read()boost::asio::async_read() 都存在接受 boost::asio::basic_streambuf 实例作为其缓冲区的重载:

    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);
    

    当调用不接受 CompletionCondition 的重载时,它相当于调用其关联的重载,其 CompletionCondition 为 boost::asio::transfer_all(),导致操作读取 streambuf.max_size() 字节。


    要将已知数量的字节读入流缓冲区,请使用:

    • boost::asio::transfer_exactly(n)CompletionCondition 限制从组合操作传输的字节数:

      std::size_t n = // ...
      boost::asio::read(socket, streambuf, 
          boost::asio::transfer_exactly(n), error);
      
    • 显式创建一个作为缓冲区的输出序列,然后将读取的字节提交到流缓冲区的输入序列中:

      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);
      

    这是一个完整的例子demonstrating这两种方法:

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

    输出:

    Writing: abc
    Read: abc
    Writing: def
    Read: def
    

    【讨论】:

      猜你喜欢
      • 2018-04-03
      • 1970-01-01
      • 2017-03-26
      • 1970-01-01
      • 2017-09-02
      • 2011-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多