2012-06-08 5 views
5

Ich schreibe eine Anwendung mit Boost asio, in der der Client und der Server Nachrichten austauschen, die mit Google Proto-Puffern serialisiert werden. Ich weiß nicht, wie groß die serialisierte Nachricht ist, die über das Netzwerk gesendet wird. Es scheint, dass die Proto-Buf-Objekte keinen Begrenzer haben.Lesen von Protobuf-Objekten mit boost :: asio :: read_async

Hier sind die Inhalte der .proto-Datei.

package tutorial; 

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

Hier ist, wie ich vom 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)); 

ich im Client schreibe die Nachricht über mit boost gesendet lese :: asio :: async_read. Wie finde ich den Wert arg als Argument für boost::asio::transfer_at_least, im folgenden Code?

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

Oder wie kann ich sicherstellen, dass boost :: async_read kehrt nach dem gesamten Objekt zu lesen?

+0

Ich weiß nicht die Antwort, aber ich bin auch interessiert, also +1. –

+0

Haben Sie Ihr Problem gelöst? Ich bin sehr daran interessiert, und Stahl hat keine klare Entscheidung über das Zusammenstellen von protobuf + boost :: asio –

Antwort

5

Korrekt, Protobufs sind nicht begrenzt. Es ist nicht bekannt, wo eine Nachricht nur aus einem Bytestrom endet - selbst wenn Sie alle Felder gesehen haben, die Sie kennen, vielleicht gibt es mehr wiederholte Elemente oder jemand hat das Proto mit einem Feld erweitert, von dem Sie nichts wissen.

Eine gängige Lösung besteht darin, Frames mit Längen (üblicherweise als VarInt s kodiert) voran zu stellen. LevelDB und Szl verwenden beide diesen Ansatz zum Beispiel. Eine VarInt kann Byte für Byte eindeutig decodiert werden, und dann wissen Sie, wie viel mehr Bytes Sie lesen müssen, bevor Sie Ihre vollständige Nachricht analysieren.

+2

Siehe auch http://stackoverflow.com/questions/2340730/are-there-c-äquivalents-for-the-protocol -buffer-delimited-io-functions-in-ja einige APIs verfügen über ein eingeschränktes Schreiben/Lesen, das Sie ganz einfach selbst implementieren können, wie in der Antwort erwähnt. – Andreas