带有zmq_proxy的ZeroMQ异步客户端和回复

时间:2014-05-05 10:26:43

标签: asynchronous proxy zeromq

我正在尝试使用libzmq C API在C模型中获取异步客户端/服务器。

我在Linux平台上使用ZeroMQ 3.2.2,我试图开始工作的模式如下所示:

>Client -> DEALER  
>
>Router -> ROUTER  
>---   proxy   ---  
>Dealer -> DEALER  
>
>Workers-> DEALER  

我需要客户端无阻塞,但仍需要接收对消息的响应。从我看到的例子中,我的理解是使用带有zmq_proxy的ROUTER-DEALER应该将消息返回给初始客户端。

但是,通过将捕获套接字附加到zmq_proxy,似乎不会路由响应。

当我将客户端更改为REQ而工作者更改为REP时,所有工作都按预期工作。 任何对我出错或误解的反馈都会受到欢迎。

3个组件(客户,经纪人和工人)在下面。

TestClient的

#include <zmq.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>

int main (void)
{
    printf ("Connecting to hello world broker...\n");

    void *ctx = zmq_ctx_new ();
    void *requester = zmq_socket (ctx, ZMQ_DEALER);
     //void *requester = zmq_socket (ctx, ZMQ_REQ);
    zmq_connect (requester, "tcp://10.1.1.31:5555");

    printf ("Sending Request  : HELLO \n");
    int rc = zmq_send (requester, "HELLO", 6, 0);

    if (rc > 0) {
        printf ("Success : Sent size ... %d!\n",rc);
    } else {
        printf("Error: %s\n", zmq_strerror(errno)); 
    }

    printf ("Wait for response ..\n");

    char buffer [256];
    zmq_recv (requester, buffer, 256, 0);

    printf ("Response Received : %s\n",&buffer);

    zmq_close (requester);
    zmq_ctx_destroy (ctx);
    return 0;
}

TestBroker

#define _MULTI_THREADED
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <zmq.h>
#include <unistd.h>
#include <assert.h>
#include <pthread.h>

#define ZFRAME_MORE     1
#define ZFRAME_REUSE    2
#define ZFRAME_DONTWAIT 4

static void *proxy_capture (void *ctx)
{
    int zerr = 0 ;
    int rRes;
    void *worker = zmq_socket (ctx, ZMQ_DEALER);
    zerr = zmq_connect (worker, "ipc://capture.ipc");

    if (zerr != 0)
    {
        printf ("\n-------------- > proxy_capture bind error : %s\n", zmq_strerror(errno));
        return 0;
    }

    while (1) {
        char buf [256];
        int rc = zmq_recv (worker, buf, 256, 0); 
        assert (rc != -1);
        printf ("Capture value : %s !\n", &buf);
    }
}

int main(int argc, char *argv[])
{
    int zerr = 0 ;
    int rc = 0 ;
    int rRes;

    // Frontend socket talks to clients over TCP Port
    void *ctx = zmq_ctx_new ();
    void *frontend = zmq_socket (ctx, ZMQ_ROUTER);
    zerr = zmq_bind (frontend, "tcp://10.1.1.31:5555");

    if (zerr != 0)
    {
        printf ("\nFrontend bind error : %s\n", zmq_strerror(errno));
        return 0;
    }

    // Backend socket talks to workers 
    void *backend = zmq_socket (ctx, ZMQ_DEALER);
    zerr = zmq_bind (backend, "tcp://10.1.1.31:6555");

    if (zerr != 0)
    {
        printf ("\nBackend bind error : %s\n", zmq_strerror(errno));
        return 0;
    }

    void *capture = zmq_socket (ctx, ZMQ_DEALER);
    zerr = zmq_bind (capture, "ipc://capture.ipc");

    if (zerr != 0)
    {
        printf ("\nCapture bind error : %s\n", zmq_strerror(errno));
        return 0;
    }

    pthread_t capworker;
    rc = pthread_create(&capworker, NULL, proxy_capture, ctx);

    zmq_proxy (frontend, backend, capture);

    while (1) {
        printf ("Broker loop …\n");
        sleep(1);
    }

    sleep(1);
    zmq_ctx_destroy (&ctx);
    printf ("\nEnd server…\n");

    return 0;
 }

TestWorker

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <zmq.h>
#include <unistd.h>
#include <assert.h>

#define ZFRAME_MORE     1
#define ZFRAME_REUSE    2
#define ZFRAME_DONTWAIT 4

int main(int argc, char *argv[])
{
    int zerr = 0 ;
    int rc = 0 ;
    int rRes;

    void *ctx = zmq_ctx_new ();
    //void *worker = zmq_socket (ctx, ZMQ_DEALER);
    void *worker = zmq_socket (ctx, ZMQ_REP);
    zerr = zmq_connect (worker, "tcp://10.1.1.31:6555");

    sleep(1);

    if (zerr != 0)
    {
        printf ("Worker connect error : %s\n", zmq_strerror(errno));
        return 0;
    }

    while (1) {
        char buf [256];
        rc = zmq_recv (worker, buf, 256, 0); 
        assert (rc != -1);
        printf ("Received : %s !\n", &buf);
        printf ("Responding to Client... !\n");

        rc = zmq_send(worker, "WORLD", 6, 0);

        if (rc > 0) {
            printf ("Success : Sent size ... %d!\n",rc);
            //break;
        } else {
            printf("Error: %s\n", zmq_strerror(errno)); 
        }
    }
    zmq_close (worker);
    zmq_ctx_destroy (ctx);

    return 0;
 }

非工作输出(客户经销商和工人经销商)

  

TestClient的

     

连接到hello world broker ...
  发送请求:你好   成功:发送尺寸... 6!
  等待回复..

     

TestBroker

     

捕捉价值:!
  夺取价值:你好! &lt; - 来自客户捕获的请求
  价值:世界! &lt; - 来自工人的回复   捕获价值:世界!

     

TestWorker

     

收到:!
  回应客户......!
  成功:发送尺寸... 6!
  收到了:你好!   回应客户......!
  成功:发送尺寸...
  6!

所以看来工作人员会响应,但路由器的响应丢失或错误地指向客户端?

请求任何帮助

1 个答案:

答案 0 :(得分:0)

我偶然发现了我对捕捉部分zmq_proxy问题的回答,我试图理解。

对于您的问题,您希望客户端是异步的,而不是使用REQ,您使用了DEALER。

以下是我如何使其异步。我的zeromq版本是4.2.1。

        //  Socket to talk to server
       void *context = zmq_ctx_new();

        void *requester = zmq_socket (context, ZMQ_REQ);
        int timeout = 5000; //Timeout of 5 seconds to make sure not having it hang either while sending or receving...
        int linger = 0;
        zmq_setsockopt (requester, ZMQ_LINGER, &linger, sizeof(int));
        zmq_setsockopt (requester, ZMQ_SNDTIMEO, &timeout, sizeof(int));
        zmq_setsockopt (requester, ZMQ_RCVTIMEO, &timeout, sizeof(int));
        int connection_status = zmq_connect (requester, "tcp://localhost:5559");

您可以通过将其设置为0来使用“逗留”,也可以在从REQ发送到代理时使用标志ZMQ_DONTWAIT