我正在使用Pipes-2.1.0包和zeromq3-haskell包构建一个小消息管道。除了我无法理解Frames的最终确定之外,一切似乎都进展顺利。
在下面的框架中,我获得了两个资源;一个zeromq上下文和一个zeromq套接字。然后我不断等待消息(以ByteStrings
的形式)在zeromq套接字上发布。
{-# LANGUAGE RebindableSyntax #-}
{-# LANGUAGE ScopedTypeVariables #-}
module PipesZeroMQ where
import Control.Frame
import Control.IMonad.Do
import Control.IMonad.Trans
import qualified Control.Monad as M
import Data.ByteString (ByteString)
import Data.String
import Prelude hiding (Monad(..))
import qualified System.ZMQ3 as ZMQ
type Address = String
fromList :: (M.Monad m) => [b] -> Frame b m (M a) (M a) ()
fromList xs = mapMR_ yield xs
publisher :: Address -> Frame Void IO (M ByteString) C ()
publisher addr = do
c <- liftU $ ZMQ.init 1
s <-liftU $ ZMQ.socket c ZMQ.Pub
liftU $ ZMQ.bind s addr
liftU $ print "Socket open for business!!!"
foreverR $ do
bs <- await
finallyF (ZMQ.close s M.>> ZMQ.term c M.>> print "ZMQ socket closed") $ do
(liftU $ ZMQ.send s [] bs)
(liftU (print "Sending message"))
现在,如果我试试这个:
λ> runFrame $ (publisher localAddress) <-< (fromList ["This", "that", "that"] >> close)
我明白了:
"Socket open for business"
"Sending message"
"ZMQ socket closed"
*** Exception: ZMQError { errno = 88, source = "send", message = "Socket operation on non-socket" }
publisher
收到一个BytesString
后确认。
为什么会这样?
我对使用Pipes-2.1.0中的Frames最终确定有什么误解?
如果我开始攻击外面的树是否有机会?
答案 0 :(得分:3)
编写publisher
函数时出错:
foreverR $ do
bs <- await
finallyF (ZMQ.close s M.>> ZMQ.term c M.>> print "ZMQ socket closed") $ do
(liftU $ ZMQ.send s [] bs)
(liftU (print "Sending message"))
您可能希望finallyF
在foreverR
循环外部放置
finallyF (...) $ foreverR $ do
bs <- await
liftU $ ZMQ.send s [] bs)
liftU (print "Sending message")
你编写它的方式,它在每次发送后都会完成,所以它正在完成你告诉它要做的事情:每次发送后完成。 finallyF
一旦其包装的操作完成,就会调用终结器,无论是成功终止还是失败。在这种情况下你也可以使用catchF
,因为循环永远不会终止:
catchF (...) $ foreverR $ do
bs <- await
liftU $ ZMQ.send s [] bs)
liftU (print "Sending message")
或者,您可以将其保留在循环内但切换到catchF
,以便在每次发送后终结器不会运行:
foreverR $ do
bs <- await
catchF (ZMQ.close s M.>> ZMQ.term c M.>> print "ZMQ socket closed") $ do
(liftU $ ZMQ.send s [] bs)
(liftU (print "Sending message"))
另外,如果您打算根据管道编写一个zeroMQ库,请与我保持联系,因为我计划在下一个版本中将帧返回到普通的monad,并对功能进行了许多新的增强。 ,例如关闭和重新初始化资源的能力。要联系我,请使用我的gmail.com地址和用户名Gabriel439。