2012-06-08 15 views
5

Tôi đang viết một ứng dụng bằng cách sử dụng Boost asio trong đó máy khách và máy chủ trao đổi các tin nhắn được tuần tự hóa bằng cách sử dụng bộ đệm proto google. Tôi không biết kích thước của thông điệp được tuần tự hóa được gửi đi qua mạng là bao nhiêu. Có vẻ như các đối tượng proto-buf không có bất kỳ dấu tách nào.Đọc các đối tượng Protobuf bằng cách sử dụng boost :: asio :: read_async

Đây là nội dung của tệp .proto.

package tutorial; 

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

Sau đây là cách Tôi viết thư này từ máy chủ

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

Trong client Tôi đang đọc tin nhắn gửi trên sử dụng tăng :: ASIO :: async_read. Làm cách nào để tìm ra giá trị của arg được đặt làm đối số cho boost::asio::transfer_at_least, trong mã bên dưới?

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

Hoặc cách khác để đảm bảo rằng tăng :: async_read trả về sau khi đọc toàn bộ đối tượng?

+0

Tôi không biết câu trả lời, nhưng tôi cũng quan tâm, vì vậy +1. –

+0

Bạn đã giải quyết vấn đề của mình chưa? Tôi rất quan tâm, và thép không có desicion rõ ràng về việc đưa protobuf + boost :: asio cùng nhau –

Trả lời

5

Chính xác, tiền nguyên thủy không được phân tách. Không biết khi nào một thông điệp kết thúc từ chỉ một bytestream - ngay cả khi bạn đã nhìn thấy tất cả các lĩnh vực bạn biết, có thể có nhiều yếu tố lặp đi lặp lại hoặc ai đó đã mở rộng proto với một lĩnh vực bạn không biết về.

Một giải pháp phổ biến là các khung tiền tố có độ dài (thường được mã hóa là VarInt s). Ví dụ: LevelDBSzl đều sử dụng phương pháp này. Một VarInt có thể được giải mã một cách rõ ràng byte theo byte, và sau đó bạn biết có bao nhiêu byte để đọc trước khi phân tích cú pháp thông điệp hoàn chỉnh của bạn.

+2

Xem thêm http://stackoverflow.com/questions/2340730/are-there-c-equivalents-for-the-protocol -buffers-delimited-io-functions-in-ja một số API có tính năng viết/đọc giới hạn mà bạn có thể dễ dàng thực hiện cho chính mình như đã đề cập trong câu trả lời. – Andreas