c++ - boost::asio 从套接字读取 n 个字节到 streambuf

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

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

    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 做同样的事情?提前谢谢你。

最佳答案

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 的重载时,它等同于使用 boost::asio::transfer_all() 的 CompletionCondition 调用其关联的重载。 ,导致操作读取 streambuf.max_size()字节。


要将已知数量的字节读入 streambuf,请使用:

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

    std::size_t n = // ...
    boost::asio::read(socket, streambuf, 
        boost::asio::transfer_exactly(n), error);
    
  • 显式创建将用作缓冲区的输出序列,然后将读取的字节提交到 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);
    

这是一个完整的例子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

关于c++ - boost::asio 从套接字读取 n 个字节到 streambuf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28929699/

相关文章:

c++ - 通过连续两次调用 boost::asio::read 检索正确的数据

c++ - 从 dll 中读取链接器信息

c++ - 从输入文件获取字符串直到整数? C++

c++ - 是否可以通过 Qt 使用 Surface Pro 3 的加速度计?

c++ - boost python 导出单例

c++ - NMAKE : fatal error U1077: cl. exe 和 nmake.exe 返回代码 '0x2'

c++ - 为什么在单击编辑文本后不显示 qml 虚拟键盘,而我在 .pro 和 main.cpp 中调用插件

c++ - 如何产生不产生超过 X 个连续元素的随机数序列

c++ - 接收第一次读取前发送到串口的数据

c++ - 让 Boost asio 工作