[英]protobuf: consecutive serialize and deserialize to/from socket
我在 C++ 客戶端和 C# 服務器之間的簡單通信在消息被序列化到套接字 (SerializeToFileDecritor) 后卡住了。
C++客戶端:
Person person;
person.set_id(54321);
person.set_name("bla");
person.mutable_address()->set_line1("sdfa");
person.mutable_address()->set_line2("asdfsdfa");
cout << person.id() << endl << person.name() << endl;
cout << person.address().line2() << endl;
person.SerializeToFileDescriptor(s);
ZeroCopyInputStream* raw_input = new FileInputStream(s);
CodedInputStream* coded_input = new CodedInputStream(raw_input);
Person person2;
person2.ParseFromFileDescriptor(s);
cout << person2.id() << endl << person2.name() << endl;
cout << person2.address().line2() << endl;
C#服務器
var sockServer = new TcpListener(2048);
sockServer.Start();
var person = new Person { Id = 123456, Name = "Fred", Address = new Address { Line1 = "Flat 1", Line2 = "The Meadows ar garą " } };
var socket = sockServer.AcceptSocket();
Stream str = new NetworkStream(socket);
var response = Serializer.Deserialize<Person>(str);
Console.WriteLine(response.Id);
Serializer.Serialize(str, person);
在我看來,這太愚蠢了,它不起作用。
如果我刪除其中任何一個:person.SerializeToFileDescriptor(s) 或 person2.ParseFromFileDescriptor(s),另一個將起作用。
我應該怎么做才能讓它們同時工作?
根 object的默認行為是將所有數據消耗到 stream 的末尾。 而且由於您沒有關閉 stream,因此永遠不會結束。
如果您的意圖是將多個對象發送到同一個套接字(這很正常),那么您需要給它一個線索。 最常見的方法是在每條消息前面加上要發送的數據長度。 這可以是一個固定的 32 int,如果方便的話,也可以是一個 varint。 然后,您可以在消費者處閱讀。
然后如何處理取決於調用者; protobuf-net 有一個DeserializeWithLengthPrefix
將處理各種 forms 編碼,有或沒有額外的字段標記(在 varint 的情況下,使其成為有效的 protobuf 流)。 例如:
Person person = Serializer.DeserializeWithLengthPrefix<Person>(str,
PrefixStyle.Fixed32, 0);
如果您打算發送多條消息,這可能很有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.