Lecture d’objects Protobuf avec boost :: asio :: read_async

J’écris une application utilisant Boost asio dans laquelle le client et le serveur échangent des messages sérialisés à l’aide de Google proto-buffers. Je ne sais pas quelle est la taille du message sérialisé envoyé sur le réseau. Il semble que les objects proto-buf n’ont pas de délimiteur.

Voici le contenu du fichier .proto.

package tutorial; message Person { required ssortingng name = 1; required int32 id = 2; optional ssortingng email = 3; } 

Voici comment j’écris depuis le serveur

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

Dans le client, je lis le message envoyé ci-dessus avec boost :: asio :: async_read. Comment savoir si la valeur de arg être définie en tant qu’argument pour boost::asio::transfer_at_least , dans le code ci-dessous?

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

Sinon, comment puis-je m’assurer que boost :: async_read revient après avoir lu l’object en entier?

Correct, les protobufs ne sont pas délimités. On ne sait pas où un message se termine dans un stream unique – même si vous avez vu tous les champs que vous connaissez, il y a peut-être plus d’éléments répétés ou quelqu’un a étendu le proto avec un champ que vous ne connaissez pas.

Une solution courante consiste à préfixer des frameworks avec des longueurs (généralement codés en tant que VarInt ). LevelDB et Szl utilisent tous deux cette approche, par exemple. Un VarInt peut être décodé sans ambiguïté octet par octet. Vous savez alors combien d’octets supplémentaires doivent être lus avant l’parsing de votre message complet.