2012-06-08 14 views
5

Sto scrivendo un'applicazione utilizzando Boost asio in cui il client e il server scambiano messaggi serializzati utilizzando i proto-buffer di google. Non so quale sia la dimensione del messaggio serializzato inviato sulla rete. Sembra che gli oggetti proto-buf non abbiano alcun delimitatore.Lettura di oggetti Protobuf tramite boost :: asio :: read_async

Ecco i contenuti del file .proto.

package tutorial; 

message Person { 
     required string name = 1; 
     required int32 id = 2; 
     optional string email = 3; 
} 

Ecco come sto scrivendo dal server

 tutorial::Person p; 
     p.set_name("abcd pqrs"); 
     p.set_id(123456); 
     p.set_email("[email protected]"); 
     write(p); 

     boost::asio::streambuf b; 
     std::ostream os(&b); 
     p.SerializeToOstream(&os); 
     boost::asio::async_write(socket_, b, 
         boost::bind(&Server::handle_write, this, 
           boost::asio::placeholders::error)); 

Nel client sto leggendo il messaggio inviato sopra utilizzando boost :: asio :: async_read. Come faccio a trovare il valore di arg come argomento per boost::asio::transfer_at_least, nel codice qui sotto?

boost::asio::async_read(socket_, response_, 
          boost::asio::transfer_at_least(arg), 
          boost::bind(&Client::handle_read_header, this, 
            boost::asio::placeholders::error)); 

Oppure come faccio a verificare che boost :: async_read ritorni dopo aver letto l'intero oggetto?

+0

Non conosco la risposta, ma mi interessa pure, quindi +1. –

+0

Hai risolto il tuo problema? Sono molto interessato a, e l'acciaio non ha la chiara volontà di mettere protobuf + boost :: asio insieme –

risposta

5

Corretto, i protobuf non sono delimitati. Non si sa dove un messaggio finisca da un semplice puntatore - anche se hai visto tutti i campi che conosci, forse ci sono altri elementi ripetuti o qualcuno ha esteso il proto con un campo di cui non sai nulla.

Una soluzione comune è prefissare i frame con lunghezze (comunemente codificati come VarInt s). LevelDB e Szl utilizzano questo approccio, ad esempio. Un VarInt può essere decodificato in modo univoco byte per byte, e quindi si sa quanti più byte leggere prima di analizzare il messaggio completo.

+2

Vedi anche http://stackoverflow.com/questions/2340730/are-there-c-equivalents-for-the-protocol -buffers-delimited-io-functions-in-ja alcune API dispongono di una scrittura/lettura delimitata che puoi facilmente implementare per te come menzionato nella risposta. – Andreas