ZeroMQ: Messaging for Many Applications对REQ -> ROUTER
通讯的评论:
如果我们使用
ROUTER
重写了我们的“Hello World”服务器,我们就能并行处理任意数量的“Hello”请求。
所以我输入hwclient.hs
并略微修改了ZeroMQ指南中的hwserver.hs
:
{-# LANGUAGE OverloadedStrings #-}
-- Hello World client
module Main where
import Control.Monad
import System.ZMQ4.Monadic
main :: IO ()
main = runZMQ $ do
liftIO $ putStrLn "Connecting to hello world server…"
requester <- socket Req
connect requester "tcp://localhost:5555"
forM_ [1..10] $ \i -> do
liftIO . putStrLn $ "Sending Hello " ++ show i ++ "…"
send requester [] "Hello"
_ <- receive requester
liftIO . putStrLn $ "Received World " ++ show i
路由器:
{-# LANGUAGE OverloadedStrings #-}
-- Hello World server
module Main where
import Control.Concurrent
import Control.Monad
import System.ZMQ4.Monadic
main :: IO ()
main = runZMQ $ do
-- Socket to talk to clients
responder <- socket Router
bind responder "tcp://*:5555"
forever $ do
buffer <- receive responder
liftIO $ do
putStrLn "Received Hello"
threadDelay 1000000 -- Do some 'work'
send responder [] "World"
但是,当我运行它时,我看到客户端发送消息,但从未收到响应。
$stack exec -- client-exe
Connecting to hello world server…
Sending Hello 1…
在我的另一个窗口中,我看到服务器收到3条消息,仅此而已:
$stack exec -- server-exe
Received Hello
Received Hello
Received Hello
Q1:
为什么客户端从未收到回复?
Q2:
为什么服务器(ROUTER
)会收到3条消息而不是1条消息?
修改
我更新了hwserver.hs
以打印出它收到的消息,而不仅仅是“你好”。
发布差异:
printf "received request: %s\n" . unpack $ buffer
替换
putStrLn "Received Hello"
服务器(路由器)显示:
$stack exec -- server-exe
received request: A§
received request:
received request: Hello
最后,这是send
的函数签名:
λ: :t send
send
:: Sender t =>
Socket z t
-> [Flag] -> Data.ByteString.Internal.ByteString -> ZMQ z ()
答案 0 :(得分:3)
以相反的顺序回答......
您的3条消息&#39;是收到的消息的3帧。第一帧由Router
套接字添加,以标识消息的来源。第二个是由Requester
套接字添加的空分隔符框架,最后一个框架包含您发送的数据。
这导致了为什么您没有得到回复,当经销商套接字发送消息时它剥离第一个消息帧并将其用作地址来识别它需要回复的客户端。由于您没有保存并将收到的第一帧附加到外发邮件,因此它只会被删除。
可悲的是,我不太了解haskell或其zeromq绑定给你一个代码解决方案,但如果你收到一个地址缓冲区,直到你读取一个空数据包,然后将数据包读入数据缓冲区。回复时发送地址缓冲区,空缓冲区然后回复。
答案 1 :(得分:0)
由于David's和user3666197's回复我放弃了identity
框架,我想出了:
{-# LANGUAGE OverloadedStrings #-}
-- Hello World server
module Main where
import Control.Concurrent
import Control.Monad
import System.ZMQ4.Monadic
import Text.Printf
import Data.ByteString.Char8 (unpack, pack)
import Data.List.NonEmpty
main :: IO ()
main = runZMQ $ do
-- Socket to talk to clients
responder <- socket Router
bind responder "tcp://*:5555"
forever $ do
response @ (identity : _ : body : []) <- receiveMulti responder
_ <- liftIO $ putStrLn . show . Prelude.length $ response
_ <- liftIO $ forM_ response (printf "received request: %s\n" . unpack)
liftIO $ putStrLn "sending world"
sendMulti responder $ identity `cons` (pack "" `cons` (pack "world" :| []))
运行
-- terminal 1
$stack exec -- client-exe
Connecting to hello world server…
Sending Hello 1…
received request: world
...
--terminal 2
$stack exec -- router-exe
3
received request: A§
received request:
received request: Hello
sending world
...