为什么ZeroMQ REQ / ROUTER示例没有收到任何消息?

时间:2016-06-04 02:46:56

标签: haskell zeromq

ZeroMQ: Messaging for Many ApplicationsREQ -> ROUTER通讯的评论:

  

如果我们使用 ROUTER 重写了我们的“Hello World”服务器,我们就能并行处理任意数量的“Hello”请求。

所以我输入hwclient.hs并略微修改了ZeroMQ指南中的hwserver.hs

Hello World Client

{-# 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 Router

{-# 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 ()

2 个答案:

答案 0 :(得分:3)

以相反的顺序回答......

您的3条消息&#39;是收到的消息的3​​帧。第一帧由Router套接字添加,以标识消息的来源。第二个是由Requester套接字添加的空分隔符框架,最后一个框架包含您发送的数据。

这导致了为什么您没有得到回复,当经销商套接字发送消息时它剥离第一个消息帧并将其用作地址来识别它需要回复的客户端。由于您没有保存并将收到的第一帧附加到外发邮件,因此它只会被删除。

可悲的是,我不太了解haskell或其zeromq绑定给你一个代码解决方案,但如果你收到一个地址缓冲区,直到你读取一个空数据包,然后将数据包读入数据缓冲区。回复时发送地址缓冲区,空缓冲区然后回复。

答案 1 :(得分:0)

由于David'suser3666197'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  
...