提高:: ASIO读取n个字节从插座到流缓冲 [英] boost::asio read n bytes from socket to streambuf

查看:201
本文介绍了提高:: ASIO读取n个字节从插座到流缓冲的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个序列化的结构,它正在通过套接字发送。我需要大块读它,因为它的领域之一包含剩余数据的大小,所以我需要阅读前几个字节,找出的长度和读取休息。这是我有:

I have got a serialized structure, which is being send via socket. I need to read it by chunks, since one of its fields contain size of data remaining, so I need to read first few bytes, find out the length and read the rest. This is what I have got:

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

但它只能读取数据,以提高:: ASIO ::缓​​冲区。我想知道如果我可以做的boost :: ASIO ::流缓冲一样吗?谢谢你在前进。

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

推荐答案

有两个<一个重载href=\"http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/reference/read.html\"><$c$c>boost::asio::read()和<一个href=\"http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/reference/async_read.html\"><$c$c>boost::asio::async_read()接受的<一个实例href=\"http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/reference/basic_streambuf.html\"><$c$c>boost::asio::basic_streambuf作为其缓冲区:

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

当调用一个不接受CompletionCondition过载,它是相当于调用其关联超载与<一个一个CompletionCondition href=\"http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/reference/transfer_all.html\"><$c$c>boost::asio::transfer_all(),使操作来读取<一href=\"http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/reference/basic_streambuf/max_size.html\"><$c$c>streambuf.max_size()字节。

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:


  • 的<一个href=\"http://www.boost.org/doc/libs/1_57_0/doc/html/boost_asio/reference/transfer_exactly.html\"><$c$c>boost::asio::transfer_exactly(n) CompletionCondition限制从组成的操作传输的字节量:

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


  • 明确创建输出序列将用作缓冲,然后commiting读入流缓冲的输入序列的字节数:

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

    输出:

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

    这篇关于提高:: ASIO读取n个字节从插座到流缓冲的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆