2015-03-08 19 views
5

Mam zserializowaną strukturę, która jest wysyłana przez gniazdo. Muszę to przeczytać fragmentami, ponieważ jedno z pól zawiera rozmiar pozostałych danych, więc muszę przeczytać kilka pierwszych bajtów, sprawdzić długość i przeczytać resztę. To jest to, co mam:boost :: asio odczytaj n bajtów z gniazda do 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; 

Brałem spojrzeć na

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

ale może tylko czytać dane do boost :: asio :: bufor. Zastanawiam się, czy mógłbym zrobić to samo z boost :: asio :: streambuf? Z góry dziękuję.

Odpowiedz

14

Istnieje przeciążenia zarówno dla boost::asio::read() i boost::asio::async_read() które akceptują wystąpień boost::asio::basic_streambuf jako bufor:

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

Dzwoniąc przeciążenie, że nie akceptuje CompletionCondition, jest to równoznaczne z wywołaniem związanym z nim przeciążenie z CompletionCondition of boost::asio::transfer_all(), powodując, że operacja odczyta streambuf.max_size() bajtów.


do odczytu znanej ilości bajtów w streambuf albo zastosowanie:

  • boost::asio::transfer_exactly(n) CompletionCondition ograniczyć ilość bajtów od złożonej operacji:

    std::size_t n = // ... 
    boost::asio::read(socket, streambuf, 
        boost::asio::transfer_exactly(n), error); 
    
  • Jawnie tworzenie sekwencji wyjściowej, która będzie służyć jako bufor, a następnie zatwierdzanie bajtów wczytanych do sekwencji wejściowej streaguf:

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

Powyżej znajduje się pełna przykład demonstrating obu tych podejść:

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

wyjściowa:

Writing: abc 
Read: abc 
Writing: def 
Read: def 
Powiązane problemy