protobuf: consecutive serialize and deserialize to/from socket

此生再无相见时 提交于 2019-12-11 03:52:15

问题


My simple communication between C++ client and C# server got stuck after a message was serialized to socket (SerializeToFileDescritor).

C++ client:

  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# server

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

It seems to me ridiculously stupid it doesn't work.

If I remove any one of these: person.SerializeToFileDescriptor(s) or person2.ParseFromFileDescriptor(s), the other will work.

What should I do to make them work both?


回答1:


The default behaviour for a root object is to consume all data to the end of the stream. And since you don't close the stream, that end never comes.

If your intention is to send multiple objects down the same socket (which is pretty normal) then you need to give it a clue. The most common approach would be to prefix each message with the length of the data about to be sent. This could be in a fixed-32 int, or in a varint if convenient. You can then read that at the consumer.

How you then handle that depends on the caller; protobuf-net has a DeserializeWithLengthPrefix that will handle various forms of encoding, with-or-without an additional field marker (in the case of varint, to make it a valid protobuf stream). For example:

Person person = Serializer.DeserializeWithLengthPrefix<Person>(str,
        PrefixStyle.Fixed32, 0);



回答2:


If you intend to send multiple messages, this might be useful.



来源:https://stackoverflow.com/questions/6233120/protobuf-consecutive-serialize-and-deserialize-to-from-socket

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!