【问题标题】:Serialize/deserialize between MONO-client and ASP.NET server - possible or not?在 MONO 客户端和 ASP.NET 服务器之间进行序列化/反序列化 - 可能与否?
【发布时间】:2011-07-24 20:49:20
【问题描述】:

我希望能够从我的 MONO 客户端在 ASP.NET(IIS 网络服务器)上加载和保存不同的对象。所以我把它们做成了 Class 对象。

例如,我有 [Score],我将使用它在服务器上生成 hiscore。

Score.cs

using System.Runtime.Serialization;
[System.Serializable]
public class Score
{
    public long Total;
    public string Name;
    public Score(){}
    public Score(string name, long total)
    {
        Total = total;
        Name = name;
    }

}

我想将此代码用作 MONO 作为客户端结构和我的 ASP.NET 服务器中的数据结构(n 层架构),我也将其用作服务器端对象。

我要做的是像这样构建一个列表数组:

List<Score> hiscores = new List<Score>();
hiscores.add (new Score("Player 1", 10000));
hiscores.add (new Score("Player 2", 20000));
hiscores.add (new Score("Player 3", 30000));
hiscores.add (new Score("Player 4", 40000));

...然后我想将它序列化为一个字节数组,这样我就可以将它作为二进制文件发布:

MemoryStream membytes = new MemoryStream(); 
BinaryFormatter binFormatter = new BinaryFormatter();
binFormatter.Serialize(membytes, hiscores );

...

但是 - 在网络服务器上,在 ASP.NET/C# 中我收到一个错误 500,告诉我它无法加载用于反序列化数据的程序集???

嗯?!我读过有人建议将组件作为外部组件?然后在两个平台上链接它,这可能在我的情况下还是我走错了路?

我可以轻松地将值从 0x00 到 0xff 的简单字节数组传输到我的 ASP.NET 并保存。但是一旦我开始在我的 List 对象上使用序列化/反序列化并将它们转换为 Byte[] 事情就搞砸了吗?

问题 如果序列化器不在同一个平台上,反序列化是不可能的吗?

是否可以将数据对象(业务对象)放在 DLL 项目中,然后在两个平台上链接/使用它,从而获得相同的组装价值?

【问题讨论】:

  • 二进制序列化只应作为同一程序的不同部分之间的传输介质,不能用于系统之间,也不能作为存储格式。太多的版本信息被捆绑在一起,格式即使是很小的软件升级也无法生存,更不用说完全不同的系统了。
  • 也许我应该编写自己的对象->二进制转换器并在双方都使用它?我有很多自定义游戏对象,因为它们需要从服务器加载并存储回来,我宁愿尽可能避免使用 XML 等。我担心 XML 版本会变得太大,双向产生太多流量。
  • 然后试试 protobuf - code.google.com/p/protobuf-net
  • 非常有趣!可能正是我需要的。谢谢。
  • @Lasse V. Karlsen,请将您的回复作为答案发布。我认为这解决了我的问题。

标签: c# asp.net serialization mono


【解决方案1】:

BinaryFormatter 生成不可互操作的二进制格式。仅当客户端和服务器都运行相同版本的 CLR 时才使用它。否则,您可以使用 XML (XmlSerializer) 或 JSON (JavaScriptSerializer) 等可互操作的格式在客户端和服务器之间进行通信。

【讨论】:

  • 不能使用 XML 或 JSON 作为其 C# 以及用于关卡地图等的大数据结构,因此我需要将数据保持在最低限度以供下载和上传 - 还有其他想法吗?
【解决方案2】:

您的大错误是为此使用BinaryFormatter。这有很多问题。

  1. 您应该信任您反序列化的数据。这在客户端-服务器应用程序中很少见。
  2. 它使用一些内部格式,我不确定.net 的不同版本之间甚至.net 和单声道之间的兼容性如何。使用格式明确的序列化程序。

这个用例的好选择是 Json 或 Xml 序列化程序。个人一般使用Json.net,但.net也有内置的Json序列化器。

BinaryFormatter 可能是您序列化复杂对象图的正确选择,不需要版本控制并且只在同一系统上读取它,因此您可以信任数据。即使在那种情况下,我也只会使用它,因为我知道没有更好的选择,而不是因为我喜欢 BinaryFormatter


既然你现在说你传输了很多数据,我会研究 protobuf-net。它是一个二进制序列化器,速度非常快并产生紧凑的数据。但是您应该使用数字 ID 注释所有属性。它的作者 Marc Gravell 在 SO 上很活跃,因此您可以期待得到很好的支持。

【讨论】:

  • 我确实信任数据,因为我编写了客户端和服务器这两个部分。但是客户端使用Mono框架,数据是大量的游戏数据,所以使用XML会对性能有很大的影响。游戏在客户端运行,但所有关卡数据、首选项、AI 等都在服务器上运行,所以我需要能够快速将数据下载到对象,然后将动作放回服务器。不是实时的。只是高效。
  • 写客户端是不够的。控制运行它的计算机是您不希望流氓客户端能够入侵您的服务器的问题。
  • 如果性能是问题,请查看 proto-buf。与大多数其他序列化程序相比,它需要更多配置,但速度非常快且数据紧凑。我假设你只是在传输高分——通常相当小。
  • 关于作弊者/黑客 - 是的,我知道那部分。那不是我的问题,我认为 XML 和 JSON 不会有什么不同?
  • 当然会有所不同。 Json/Xml 可以向您发送无效数据,但如果反序列化器有任何好处,它们将不允许攻击者执行代码。大多数其他序列化程序都通过公共属性,需要注释,... BinarySerializer 可以简单地将邪恶的东西写入您的私有字段,实例化任意类型,...也许可以控制它,但我不知道如何。
【解决方案3】:

发布我自己的答案,因为我实际上设法让它在没有额外内容的情况下工作

首先,感谢所有关于额外库的好建议,但我最初的问题是关于是否可以通过序列化使 MONO 和 ASP.NET 进行通信。

答案是:是的!

我所要做的就是构建一个单独的类项目 (DLL),在其中放置我需要序列化的所有数据结构。

然后在两个平台上都引用它,瞧,相同的 DLL = 相同的程序集,并且两个平台都同意序列化和反序列化没有问题。

二进制结果/流量/空格的注意事项

我同意,与此处建议的其他一些插件/库相比,二进制数据似乎有点“矫枉过正”。但是没有任何额外的库是可能的。

这是我最初的目标。

【讨论】:

    【解决方案4】:

    我使用了 Mike Talbot 的 Silverlight 串行器 http://whydoidoit.com/2010/04/08/silverlight-serialization/ 这是非常轻量级的,应该适用于 MONO 和 .NET

    【讨论】:

    • 也很有趣,但我偶然发现了这个:“SilverlightSerializer 是一个在 .NET 和 Silverlight 中工作的二进制序列化程序,允许您在两个实例之间移动对象或在本地存储和检索它们。” - 我需要在客户端和服务器之间移动,从 MONO 到 NET 再返回?
    猜你喜欢
    • 2015-12-09
    • 1970-01-01
    • 1970-01-01
    • 2019-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多