2012-06-08 8 views
5

Estoy escribiendo una aplicación usando Boost asio en la que el cliente y el servidor intercambian mensajes que se serializan utilizando los proto-buffers de Google. No sé cuál es el tamaño del mensaje serializado que se envía a través de la red. Parece que los objetos proto-buf no tienen ningún delimitador.Lectura de objetos Protobuf usando boost :: asio :: read_async

Aquí están los contenidos del archivo .proto.

package tutorial; 

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

Así es como estoy escribiendo desde el servidor

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

En el cliente que estoy leyendo el mensaje enviado anteriormente usando ASIO impulso :: :: async_read. ¿Cómo puedo averiguar que el valor de arg se establezca como argumento en boost::asio::transfer_at_least, en el código siguiente?

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

O bien, ¿cómo puedo asegurarme de que boost :: async_read regrese después de leer todo el objeto?

+0

No sé la respuesta, pero también estoy interesado, así que +1. –

+0

¿Has resuelto tu problema? Estoy muy interesado, y Steel no tiene una clara idea acerca de poner protobuf + boost :: asio juntos. –

Respuesta

5

Correcto, los protobufs no están delimitados. No hay forma de saber dónde termina un mensaje simplemente de una corriente secundaria: incluso si ha visto todos los campos que conoce, tal vez haya más elementos repetidos o alguien haya extendido el protocolo con un campo que desconoce.

Una solución común es prefijar marcos con longitudes (comúnmente codificadas como VarInt s). LevelDB y Szl ambos usan este enfoque, por ejemplo. A VarInt se puede decodificar de manera inequívoca byte por byte, y luego se sabe cuántos bytes más leer antes de analizar su mensaje completo.

+2

Ver también http://stackoverflow.com/questions/2340730/are-herehere-c-equivalents-for-the-protocol -buffers-delimited-io-functions-in-ja Algunas API presentan escritura/lectura delimitada que puede implementar fácilmente por sí mismo como se menciona en la respuesta. – Andreas

Cuestiones relacionadas