【发布时间】:2016-06-19 01:05:50
【问题描述】:
ZeroMQ: Messaging for Many Applicationscmets on REQ -> ROUTER 通讯:
如果我们使用
ROUTER重写我们的“Hello World”服务器,我们将能够并行处理任意数量的“Hello”请求。
所以我输入了 hwclient.hs 并稍微修改了 ZeroMQ 指南中的 hwserver.hs:
Hello World 客户端
{-# 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
还有路由器:
Hello World 路由器
{-# 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 以打印出它收到的消息,而不是简单的“Hello”。
发布差异:
printf "received request: %s\n" . unpack $ buffer
替换
putStrLn "Received Hello"
而服务器(Router)显示:
$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 ()
【问题讨论】:
-
Haskell 绑定是否自动检测和处理 API
REQ/ROUTER行为的强制部分?(cit.:“当 一个ZMQ_REQ套接字连接到一个ZMQ_ROUTER套接字,除了原始对等方的身份之外,收到的每条消息应包含一个空的分隔符消息因此,应用程序看到的每个接收到的消息的整个结构变成:一个或多个 identity 部分、delimiter 部分、一个或多个 body “ ) -
您还想了解 Pieter Hintjens 的书 [ Code Connected, Vol. 1 ], page 97 ( >>> hintjens.wdfiles.com/local--files/main%3Afiles/cc1pe.pdf ), (cit.: "
worker必须保存信封 (这是所有部分并包括空消息帧),然后它可以对数据部分执行所需的操作。请注意,REP套接字会自动执行此操作,但我们使用的是 @ 987654348@模式... ") -
( cit.: 我们可以以两种不同的方式使用
ROUTER: • 作为在前端和后端套接字之间切换消息的代理。 • 作为读取消息并对其进行操作。在第一种情况下,ROUTER只是读取所有帧,包括人工身份帧,然后盲目地传递它们。在第二种情况下,ROUTER必须知道发送的回复信封的格式。由于另一个对等方是REQ套接字,ROUTER获取标识帧、空帧,然后是数据帧。"