【问题标题】:How to serialize/deserialize objects sent over the network in Haskell?如何在 Haskell 中序列化/反序列化通过网络发送的对象?
【发布时间】:2014-12-16 07:32:57
【问题描述】:

我看到有很多方法可以序列化/反序列化 Haskell 对象:

在我的应用程序中,我想设置一个简单的 TCP 客户端-服务器,客户端可以在其中发送序列化的 Haskell 记录对象。如何在这些序列化替代方案之间做出选择?

此外,当序列化为字符串的对象使用Network.Socket 通过网络发送时,会返回字符串。是否有一个更高级别的库,可以在整个 TCP 消息的级别上工作?换句话说,有没有办法避免在接收端编写解析代码:

  • 收集一系列 recv() 调用的结果,
  • 检测到已接收到整个对象,并且
  • 然后解析成haskell类型?

在我的应用程序中,对象不会太大(最大可能约为 ~1MB)。

【问题讨论】:

标签: sockets haskell serialization


【解决方案1】:

至于你问题的第二部分,需要两件事:

  1. 一种增量解析器,它不需要将整个文档都保存在内存中即可开始解析,并且可以接收来自网络的部分数据块。此外,当解析成功时,它必须返回任何“剩余数据”以及解析值。

  2. 具有“回推功能”的数据源,可让您“取消读取”任何剩余内容,以便下次解析尝试使用它们。

提供 (1) 的最受欢迎的库是 attoparsec。至于(2),所有三个主要的流媒体库(conduitio-streamspipes)都提供了某种推送功能(后者使用辅助的 pipes-parse 包)。所有三个库都可以与 attoparsec 解析器集成(请参阅 hereherehere)。

(当然,另一种选择是在每条消息的前面加上其长度是只读的确切字节数。)

【讨论】:

    【解决方案2】:

    要回答您问题的第一部分(关于数据序列化),我想说您列出的所有内容听起来都不错。由于您正在处理相当大的(1MB)序列化,我认为最重要的是懒惰。还有另一个序列化库,称为cereal,它具有严格的序列化,您不希望这样,因为您需要在发送之前在内存中构建它。我会向 aeson (http://hackage.haskell.org/package/aeson-0.8.0.2/docs/Data-Aeson.html) 大声喊叫,您可以使用 GHC Generics 来获得类似这样的简单内容:

    data Shape = Rect Int Int | Circle Double | Other String Int
      deriving (Generic)
    instance FromJSON Shape  -- uses a default
    instance ToJSON Shape    -- uses a default
    

    然后,砰!,您可以访问 encodedecode 方法。我不知道更高级别的 TCP 库。希望其他人对此有更深入的了解。

    【讨论】:

    • 谢谢,你和 danidiaz 的回答都很有用。
    猜你喜欢
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多