C# - 更高效的数据包序列化

3
我正在创建一个程序,需要在客户端和服务器之间高效地发送数据。为了清晰地组织数据包,我使用序列化技术。然而,当我对这些数据包进行序列化时,数据变得不必要地大。为了让您理解我的需求,我将解释我正在做的事情。
我的数据包类的工作方式如下:我有一个 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 - https://github.com/antmicro/Migrant。它可以在生成的数据中以小的开销序列化您的类,并且几乎不需要样板代码。实际上,对于简单情况,它不需要任何代码。此外,它还提供了诸如具有循环等复杂对象图形的功能。 - Piotr Zierhoffer
我会看一下...如果看起来切换到它不需要太多的工作,我会尝试一下。谢谢。 - Jordan
BinaryFormatter 不是进行机器到机器序列化的好选择,如果两台机器具有不同版本的核心 .NET DLL(例如一台机器还没有运行 Windows 更新时,.NET 的热修复已经发布),则您的数据将无法反序列化。 (我甚至不建议将其用于保存到磁盘以供同一台机器使用,唯一可以在不担心反序列化问题的情况下使用它的地方是在同一台机器上进行 IPC 通信) - Scott Chamberlain
我明白了,那么除了使用这些整洁的类来保存数据之外,我还能用什么方式发送我的数据呢? - Jordan
哦,我以为你建议我完全避免这种序列化。 - Jordan
显示剩余2条评论
1个回答

3
你所说的“为什么序列化数据比使用BinaryWriter手动写信息要大”,其中的“信息”指的是“属性值”。然而,你使用的序列化器不仅序列化了数据,还序列化了一些有关类的信息。通过在文本编辑器中查看序列化数据,可以看到这一点。 问题: 是否有任何方法可以减少序列化数据的大小,同时仍然将数据组织成自己的类?
使用更专门的序列化方式,例如protobufPiotr建议的库等。
此外,我认为你的序列化代码不应该驻留在Packet基类中,而应该放在一个单独的类中,如PacketEncoder。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接