在消息序列化到套接字 (SerializeToFileDescriptor) 后,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# 服务器
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),另一个将起作用。
我应该怎么做才能让它们同时工作?
默认行为对于根对象就是消耗所有数据到流的末尾。由于您不关闭流,因此结束永远不会到来。
如果您的意图是在同一个套接字上发送多个对象(这很正常),那么您需要给它一个线索。最常见的方法是在每条消息前加上要发送的数据的长度前缀。这可以是固定的 32 int,或者如果方便的话可以是 varint。然后您可以在消费者处阅读该内容。
然后你如何处理取决于调用者; protobuf-net 有一个DeserializeWithLengthPrefix
它将处理各种形式的编码,有或没有附加字段标记(在 varint 的情况下,使其成为有效的 protobuf 流)。例如:
Person person = Serializer.DeserializeWithLengthPrefix<Person>(str,
PrefixStyle.Fixed32, 0);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)