【问题标题】:c# - More efficient serialization for packetsc# - 更高效的数据包序列化
【发布时间】:2014-01-19 23:21:10
【问题描述】:

我正在创建一个程序,它必须在客户端和服务器之间有效地发送数据。为了清楚地组织数据包,我使用了序列化。但是,当我序列化这些数据包时,数据会变得不必要地大。我将解释我在做什么,以便您了解我需要什么。

我的数据包类是这样工作的。我有一个 Packet 对象:

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable]
public class Packet
{
    public static byte[] Serialize(Object o)
    {
        MemoryStream ms = new MemoryStream();
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(ms, o);
        return ms.ToArray();
    }

    public static Object Deserialize(byte[] bt)
    {
        MemoryStream ms = new MemoryStream();
        BinaryFormatter bf = new BinaryFormatter();

        ms.Write(bt, 0, bt.Length);
        ms.Position = 0;

        object obj = bf.Deserialize(ms);

        ms.Close();

        return obj;
    }
}

然后我可以创建其他继承自 Packet 类的类,这是一个示例:

using System;

[Serializable]
public class PacketUserInfo : Packet
{
    public string Name;
    public int Age;
}

那么,就很简单了,把它放到一个字节数组中发送出去(当然上面的数据包只是一个例子)。但是,结果数组的大小至少比我使用 BinaryWriter 并手动写入信息时大 10 倍。

为什么序列化的数据这么大?有没有什么办法可以减少它,同时仍然保持一切都以包作为自己的类来组织?

注意:我只是想序列化这样的简单属性,没什么特别的。

【问题讨论】:

  • 虽然我无法为您提供这种行为的确切原因,但我想推荐一个序列化库,我与人合着了 Migrant - github.com/antmicro/Migrant 。它允许以很少的结果数据开销和几乎没有样板代码来序列化您的类。事实上,对于简单的情况,它不需要任何代码。它还提供了诸如具有循环的对象的复杂图等功能。
  • 我会看看它...如果看起来切换到它不需要太多工作,我会尝试它。谢谢。
  • BinaryFormatter 不是机器到机器搜索的好选择,如果两台机器具有不同的核心 .NET DLL 的 DLL 版本(假设一台机器尚未运行它的 Windows 更新,当一个修补程序到.NET 出来)您的数据将无法解串。 (我什至不建议将它保存到同一台机器的磁盘,唯一不用担心解串问题的地方是用于同一台机器上的 IPC 通信)
  • 我明白了,那么在将数据保存在这些整洁的类中的同时,我还能如何发送数据?
  • 正如我所说,在大多数情况下,Migrant 不需要任何额外的代码。请记住,Migrant 针对大部分数据进行了优化,针对小类的进一步优化尚未到来。例如,如果您只是序列化这样一个小数据包的一部分,它可能会比二进制格式化程序占用更多的空间。如果您需要任何帮助,请写信至 github 上提供的电子邮件,我们会尽快回复。

标签: c# sockets serialization


【解决方案1】:

您在哪里说“为什么序列化数据 [...] 比我使用 BinaryWriter 并手动写入信息时更大”,带有 信息 em> 你的意思是属性值。然而,您使用的序列化程序不仅会序列化 数据,还会序列化有关 的一些信息。您可以通过在文本编辑器中查看序列化数据来查看这一点。

有没有什么办法可以减少它,同时仍然保持一切都以数据包作为自己的类进行组织?

使用更专业的序列化,例如protobuf 或库suggested by @Piotr

另外,我认为您的序列化代码不应驻留在Packet 基类中,而应驻留在单独的类中,例如PacketEncoder

【讨论】:

    猜你喜欢
    • 2013-05-04
    • 2011-03-22
    • 1970-01-01
    • 1970-01-01
    • 2011-10-05
    • 2013-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多