protobuf:连续序列化和反序列化到/从套接字 [英] protobuf: consecutive serialize and deserialize to/from socket

查看:39
本文介绍了protobuf:连续序列化和反序列化到/从套接字的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在将消息序列化为套接字 (SerializeToFileDescriptor) 后,我的 C++ 客户端和 C# 服务器之间的简单通信卡住了.

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

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

在我看来这是愚蠢的,它不起作用.

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

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

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?

推荐答案

根对象的默认行为是将所有数据消耗到流的末尾.既然你没有关闭流,那末就永远不会到来.

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.

如果您打算将多个对象发送到同一个套接字(这很正常),那么您需要给它一个提示.最常见的方法是为每条消息添加将要发送的数据长度作为前缀.这可以是一个固定的 32 整数,如果方便的话,也可以是 varint.然后,您可以在消费者处阅读该内容.

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.

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

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

这篇关于protobuf:连续序列化和反序列化到/从套接字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆