protobuf:连续序列化和反序列化到套接字

时间:2011-06-03 22:04:10

标签: c# c++ protocol-buffers protobuf-net

在将消息序列化到socket(SerializeToFileDescritor)之后,我在C ++客户端和C#服务器之间的简单通信被卡住了。

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

在我看来,这是荒谬的,它不起作用。

如果我删除其中任何一个:person.SerializeToFileDescriptor(s)或person2.ParseFromFileDescriptor(s),另一个将起作用。

我应该怎样做才能使它们兼顾?

2 个答案:

答案 0 :(得分:2)

根对象的默认行为是将所有数据都消耗到流的末尾。由于你没有关闭流,因此永远不会到来。

如果您打算在同一个套接字上发送多个对象(这很正常),那么您需要给它一个线索。最常见的方法是在每条消息前面加上要发送的数据的长度。这可以是固定的32 int,如果方便的话也可以是varint。然后,您可以在消费者处阅读。

然后如何处理这取决于调用者; protobuf-net有一个DeserializeWithLengthPrefix,可以处理各种形式的编码,带或不带额外的字段标记(在varint的情况下,使其成为有效的protobuf流)。例如:

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

答案 1 :(得分:2)

如果您打算发送多封邮件,this可能会有用。