2015-03-08 155 views
5

我有一个序列化结构,它是通过套接字发送的。我需要通过块读取它,因为它的一个字段包含剩余数据的大小,所以我需要先读取几个字节,找出长度并阅读剩余的部分。这是我有:boost :: asio从套接字读取n个字节到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); 

但它只能读取数据,以提高:: ASIO ::缓冲区。我想知道如果我可以用boost :: asio :: streambuf做同样的事情吗?先谢谢你。

回答

14

有两个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(),导致操作读取streambuf.max_size()字节。


为了读取字节的已知量成流缓冲,无论是使用:

  • 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 
相关问题