标签: protobuf-net

如何在Protobuf中发送多种类型的对象?

我正在实现客户端 - 服务器应用程序,并正在研究序列化和传输数据的各种方法.我开始使用Xml Serializers,它工作得很好,但是生成数据很慢,并且生成大对象,特别是当它们需要通过网络发送时.所以我开始研究Protobuf和protobuf-net.

我的问题在于protobuf没有发送类型信息.使用Xml Serializers,我能够构建一个包装器,它将在同一个流上发送和接收任何各种(可序列化的)对象,因为序列化为Xml的对象包含对象的类型名称.

ObjectSocket socket = new ObjectSocket();
socket.AddTypeHandler(typeof(string));  // Tells the socket the types
socket.AddTypeHandler(typeof(int));     // of objects we will want
socket.AddTypeHandler(typeof(bool));    // to send and receive.
socket.AddTypeHandler(typeof(Person));  // When it gets data, it looks for
socket.AddTypeHandler(typeof(Address)); // these types in the Xml, then uses
                                        // the appropriate serializer.

socket.Connect(_host, _port);
socket.Send(new Person() { ... });
socket.Send(new Address() { ... });
...
Object o = socket.Read();
Type oType = o.GetType();

if (oType == typeof(Person))
    HandlePerson(o as …
Run Code Online (Sandbox Code Playgroud)

c# serialization protocol-buffers protobuf-net

8
推荐指数
1
解决办法
5462
查看次数

protobuf-net消息序列化大小属性

我们使用protobuf-net对公共协议基于Google Protocol Buffers的应用程序中的消息进行序列化和反序列化.该库非常出色,涵盖了除此之外的所有要求:我们需要在消息实际序列化之前找出序列化的消息长度(以字节为单位).

这个问题已经在一年半前提出过,根据Marc的说法,唯一的方法就是序列化到MemoryStream并.Length随后读取属性.在我们的例子中这是不可接受的,因为MemoryStream在幕后分配一个字节缓冲区,我们必须避免这种情况.

来自同一回复的这一行给了我们希望它毕竟是可能的:

如果你澄清用例是什么,我相信我们可以轻松地提供它(如果它还没有).

这是我们的用例.我们有大小在几个字节和两兆字节之间变化的消息.应用程序预先分配用于套接字操作和序列化/反序列化的字节缓冲区,一旦预热阶段结束,就不能创建额外的缓冲区(提示:avoding GC和堆碎片).字节缓冲区基本上是合并的.我们还希望尽可能避免在缓冲区/流之间复制字节.

我们提出了两种可能的策略,它们都需要预先设置邮件大小:

  1. 使用(大)固定大小的字节缓冲区并序列化所有可以放入一个缓冲区的消息; 使用发送缓冲区的内容Socket.Send.我们必须知道下一条消息何时无法放入缓冲区并停止序列化.如果没有消息大小,实现此目的的唯一方法是等待异常发生Serialize.
  2. 使用(小)可变大小的字节缓冲区并将每条消息序列化为一个缓冲区; 使用发送缓冲区的内容Socket.Send.为了从池中检出具有适当大小的字节缓冲区,我们需要知道序列化消息有多少字节.

因为协议已经定义(我们不能改变它)并且要求消息长度前缀为Varint32,所以我们不能使用SerializeWithLengthPrefix方法.

那么是否可以添加一种估计消息大小而无需序列化到流中的方法?如果它不适合图书馆的当前功能集和路线图,但是可行,我们有兴趣自己扩展图书馆.我们也在寻找替代方法,如果有的话.

c# protobuf-net

8
推荐指数
1
解决办法
1954
查看次数

C#.net协议缓冲区 - protobuf-net支持序列化对象值字典?

我是协议缓冲区的新手,我正在为VS2010使用protobuf-net.从我在这里阅读协议缓冲区中的字典,似乎protobuf不能将具有对象类型的字典序列化为值.但在他的网站上我读到了这个:

关于类型的说明

支持的:

自定义类:标记为数据契约具有Silverlight的无参数构造函数:公共许多常见原语等单维数组:T [] List/IList Dictionary/IDictionary任何实现IEnumerable并具有Add(T)方法的类型代码假定类型在选定成员周围是可变的.因此,不支持自定义结构,因为它们应该是不可变的.

这似乎得到了支持.

我可以像这样成功编译一个对象列表:

message ValuesObject {
    optional int32 SomeVal = 1;
    repeated SomeClass ListOfSomeClassTypes = 2;
}
Run Code Online (Sandbox Code Playgroud)

这适用于List<SomeClass>.为什么我不能使用protobuf-net序列化Dictionary<int, SomeClass>?该序列化的消息是什么样的Dictionary<int, SomeClass>

c# protocol-buffers protobuf-net

8
推荐指数
1
解决办法
5839
查看次数

Protobuf-net与官方谷歌Protobuf for C++(消息编码)不兼容

我们在.NET中有一些(很多)类.我们使用protobuf-net来标记它们,并通过谷歌原始库为C++代码端生成.proto包装器.

所以我有一条消息(C++ DebugString()在一些EventBase类上(在.NET中EventCharacterMoved 继承,EventBase而在C++中我只是写入可选属性)):

UserId: -2792
EventCharacterMoved {
  Coordinates {
    Position {
      X: 196.41913
      Y: 130
      Z: 213
    }
    Rotation {
      X: 207
      Y: 130
      Z: 213
    }
  }
  OldCoordinates {
    Position {
      X: 196.41913
      Y: 130
      Z: 213
    }
    Rotation {
      X: 207
      Y: 130
      Z: 213
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

(来自这样的.proto文件)

message Coordinates {
   optional TreeFloat Position = 1;
   optional TreeFloat Rotation = 2;
}
message EventBase {
   optional int32 UserId = …
Run Code Online (Sandbox Code Playgroud)

.net c# c++ protocol-buffers protobuf-net

8
推荐指数
1
解决办法
2343
查看次数

UWP/.NET Native和iOS上的Protobuf-net

我有一个基于.NET Standard 1.4的Xamarin.Forms应用程序,它使用protobuf-net在数据库中存储对象,稍后将发送到WCF服务.

在Android和UWP上"托管"一切正常但是 - 在搜索了无法再访问的存储库,文章和博客文章之后,以及在尝试使预编译工具工作之后,但是失败了 - 我有一个简单的(可能)问题:如何让protobuf-net在UWP/.NET Native和iOS/Xamarin等"受限"环境中工作?

c# protobuf-net ios .net-native xamarin.forms

8
推荐指数
1
解决办法
825
查看次数

协议缓冲区是否支持使用共享引用对象图的序列化?

请观察以下简单程序(基于protobuf-net项目v1 wiki的示例):

using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using ProtoBuf;

namespace HelloProtoBuf
{
  [ProtoContract]
  class Person
  {
    [ProtoMember(1)]
    public int Id { get; set; }
    [ProtoMember(2)]
    public string Name { get; set; }
    [ProtoMember(3)]
    public Address Address { get; set; }
  }
  [ProtoContract]
  class Address
  {
    [ProtoMember(1)]
    public string Line1 { get; set; }
    [ProtoMember(2)]
    public string Line2 { get; set; }
  }


  class Program
  {
    static void Main(string[] args)
    {
      var person = new Person
      {
        Id = 12345, …
Run Code Online (Sandbox Code Playgroud)

protocol-buffers protobuf-net

7
推荐指数
1
解决办法
3339
查看次数

Google Protocol Buffers Serialization挂起写入1GB +数据

我正在使用协议缓冲区序列化序列化大型数据集.当我的数据集包含400000个大小约为1 GB的自定义对象时,序列化将在3~4秒内返回.但是当我的数据集包含大约1.2 GB的450000个组合大小的对象时,序列化调用永远不会返回并且CPU会不断消耗.

我正在使用Protocol Buffers的.NET端口.

.net c# serialization protocol-buffers protobuf-net

7
推荐指数
2
解决办法
1880
查看次数

异步protobuf序列化

protobuf-net实现的一个限制是它同步调用底层流.通过不提供异步API,例如BeginSerialize/EndSerialize或TPL等价物,我们被迫绑定一个等待同步流I/O的线程.

有没有计划在protobuf-net中提供异步方法,或者有任何创造性的方法来解决这个问题?

.net c# protobuf-net

7
推荐指数
1
解决办法
2282
查看次数

使用NetTcpBinding WCF服务获取IEnumerable <T>语义?

首先,这不是IEnumerable <T>的副本作为WCF方法的返回类型,我想我明白WCF架构只允许传输可以填充到消息中的具体类型.

其次,我们的设置不是一般服务,而是通过C#+ WCF + NetTcpBinding + Protobuf(仅)连接一组专有应用程序,因此我们可能有更多空间来处理某些需要更具约束力中性的技巧.

第三,提出不同的RPC或消息框架既不是我的地方,也不是这个问题.


出于这个问题的目的,"IEnumerable语义"是:

  • 返回的顺序可以任意大-因此它是不是可以将序列转换为List或相似.
  • 这是不是事先知道有多少项目会被退回
  • 来电者可以使用foreach并完成它.

在本地程序集中,C#接口看起来像这样:

interface IStuffProvider {
  IEnumerable<Stuff> GetItems(); // may open large file or access database
}
Run Code Online (Sandbox Code Playgroud)

您无法将其直接映射到WCF服务.可能达到相同效果的东西可能如下所示:

[ServiceContract(SessionMode = SessionMode.Required)]
interface IStuffService {
  [OperationContract]
  void Reset(); // may open large file or access database
  [OperationContract]
  List<Stuff> GetNext(); // return next batch of items (empty list if no more available)
} …
Run Code Online (Sandbox Code Playgroud)

c# wcf remoteobject protobuf-net nettcpbinding

7
推荐指数
1
解决办法
508
查看次数

如何避免在Protobuf上的WCF中有重复的对象

我有一个小单元测试来测试循环依赖.

我的目标如下:

[ProtoContract]
public class Node
{
    [ProtoMember(1)]
    public String Name { get; set; }

    [ProtoMember(2,AsReference = true)]
    public List<Node> Childs { get; set; }

    public Node()
    {
        Childs = new List<Node>();
    }
}
Run Code Online (Sandbox Code Playgroud)

以下服务:

[ServiceContract]
public interface INodeService : IService
{
    [OperationContract]
    Task<Node> GetCyclicNodes();
}

public class NodeService : Service, INodeService
{
    public async Task<int> Add(int a, int b)
    {
        return a + b;
    }

    public async Task<Node> GetCyclicNodes()
    {
        Node nodeA = new Node() {Name = "Node A"}; …
Run Code Online (Sandbox Code Playgroud)

wcf protocol-buffers protobuf-net

7
推荐指数
1
解决办法
251
查看次数