haskell - 使用 Haskell 管道的重要协议(protocol)

标签 haskell conduit network-conduit

我试图弄清楚如何使用 Haskell 管道实现一个不平凡的协议(protocol)(通过 TCP)。我认为重要的例子:

  • 读取一些 header 字节,如果它们与预期匹配,则忽略它们并继续;否则,向客户端返回错误。
  • 读取指示字段长度的 N 个字节,然后将该字节数读入字节串。
  • 在客户端和服务器之间执行来回握手,就像能力协商一样。协商后,根据协商的内容调用不同的服务器端代码。 (例如协商服务器和客户端同意的协议(protocol)版本)
  • 如果客户端未能足够快地协商协议(protocol),则使连接超时,并向客户端发送错误

到目前为止,我正在努力......任何帮助或指向一些示例代码的指针将不胜感激!

最佳答案

这个问题有点模糊,但如果您正在寻找基于先前解析的结果控制管道中操作的示例,netstring 协议(protocol)的实现可能就足够了:

#!/usr/bin/env stack
-- stack --resolver lts-10.3 script
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE OverloadedStrings #-}
import Conduit
import Data.ByteString (ByteString)
import Data.Word8 (_colon, _comma, _0, _9, Word8)
import Control.Exception.Safe (throwString)

netstring :: forall m. MonadThrow m => ConduitM ByteString ByteString m ()
netstring = do
  len <- takeWhileCE (/= _colon) .| foldMCE addDigit 0
  mchar1 <- headCE
  case mchar1 of
    Just c
      | c == _colon -> return ()
      | otherwise -> throwString $ "Didn't find a colon: " ++ show c
    Nothing -> throwString "Missing colon"
  takeCE len
  mchar2 <- headCE
  case mchar2 of
    Just c
      | c == _comma -> return ()
      | otherwise -> throwString $ "Didn't end with a comma: " ++ show c
    Nothing -> throwString "Missing trailing comma"
  where
    addDigit :: Int -> Word8 -> m Int
    addDigit total char
      | char < _0 || char > _9 = throwString "Invalid character in len"
    addDigit total char = return $! total * 10 + fromIntegral (char - _0)

main :: IO ()
main = do
  let bs = "5:hello,6: world,"
  res <- runConduit
       $ yield bs
      .| ((,) <$> (netstring .| foldC) <*> (netstring .| foldC))
  print res

关于haskell - 使用 Haskell 管道的重要协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48594530/

相关文章:

haskell - 具有动态请求/响应类型的管道?

haskell - cofree comonad 的可展开实例

haskell - 如何推断liftM2 (==) id和(\x->x+1) id的类型

haskell - 具有类约束的 GHC 重写规则

Haskell 服务器不回复客户端

sockets - 导管和 socket : allow multiple connections

haskell - 使用 mapM 保持懒惰

haskell - 导管异常

parsing - Haskell:用二进制懒惰地读取二进制文件