如何在 Haskell 中序列化/反序列化通过网络发送的对象?
Posted
技术标签:
【中文标题】如何在 Haskell 中序列化/反序列化通过网络发送的对象?【英文标题】:How to serialize/deserialize objects sent over the network in Haskell? 【发布时间】:2014-12-16 07:32:57 【问题描述】:我看到有很多方法可以序列化/反序列化 Haskell 对象:
Data.Serialize -> 编码、解码函数 Data.Binary http://code.haskell.org/binary/ MsgPack、JSON、BSON 等在我的应用程序中,我想设置一个简单的 TCP 客户端-服务器,客户端可以在其中发送序列化的 Haskell 记录对象。如何在这些序列化替代方案之间做出选择?
此外,当序列化为字符串的对象使用Network.Socket 通过网络发送时,会返回字符串。是否有一个更高级别的库,可以在整个 TCP 消息的级别上工作?换句话说,有没有办法避免在接收端编写解析代码:
收集一系列 recv() 调用的结果, 检测到已接收到整个对象,并且 然后解析成haskell类型?在我的应用程序中,对象不会太大(最大可能约为 ~1MB)。
【问题讨论】:
Have you tried searching for TCP on Hackage? 【参考方案1】:至于你问题的第二部分,需要两件事:
一种增量解析器,它不需要将整个文档都保存在内存中即可开始解析,并且可以接收来自网络的部分数据块。此外,当解析成功时,它必须返回任何“剩余数据”以及解析值。
具有“回推功能”的数据源,可让您“取消读取”任何剩余内容,以便下次解析尝试使用它们。
提供 (1) 的最受欢迎的库是 attoparsec。至于(2),所有三个主要的流媒体库(conduit、io-streams 和 pipes)都提供了某种推送功能(后者使用辅助的 pipes-parse 包)。所有三个库都可以与 attoparsec 解析器集成(请参阅 here、here 和 here)。
(当然,另一种选择是在每条消息的前面加上其长度是只读的确切字节数。)
【讨论】:
【参考方案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
然后,砰!,您可以访问 encode
和 decode
方法。我不知道更高级别的 TCP 库。希望其他人对此有更深入的了解。
【讨论】:
谢谢,你和 danidiaz 的回答都很有用。以上是关于如何在 Haskell 中序列化/反序列化通过网络发送的对象?的主要内容,如果未能解决你的问题,请参考以下文章