zoukankan      html  css  js  c++  java
  • ZeroMQ_09 ZMQ多线程编程

    ZMQ多线程编程基本规则:

    • 不要在不同的线程之间访问同一份数据,如果要用到传统编程中的互斥机制,那就有违ZMQ的思想了。唯一的例外是ZMQ上下文对象,它是线程安全的。

    • 必须为进程创建ZMQ上下文,并将其传递给所有你需要使用inproc协议进行通信的线程;

    • 你可以将线程作为单独的任务来对待,使用自己的上下文,但是这些线程之间就不能使用inproc协议进行通信了。这样做的好处是可以在日后方便地将程序拆分为不同的进程来运行。

    • 不要在不同的线程之间传递套接字对象,这些对象不是线程安全的。从技术上来说,你是可以这样做的,但是会用到互斥和锁的机制,这会让你的应用程序变得缓慢和脆弱。唯一合理的情形是,在某些语言的ZMQ类库内部,需要使用垃圾回收机制,这时可能会进行套接字对象的传递。

    下面我们看一个多线程的Hello word服务

    Client:

    #include "../zhelpers.h"
    #include <stdio.h>
    
    int main (void) 
    {
        void *context = zmq_ctx_new ();
    
        //  Socket to talk to server
        void *requester = zmq_socket (context, ZMQ_REQ);
        zmq_connect (requester, "tcp://localhost:5555");
    
        int request_nbr;
        for (request_nbr = 0; request_nbr != 10; request_nbr++) {
            char strDst[256] = {0};
            snprintf(strDst,256,"Hello %d",request_nbr);
            s_send (requester, strDst);
            char *string = s_recv (requester);
            printf ("Received reply %d [%s]
    ", request_nbr, string);
            free (string);
        }
        zmq_close (requester);
        zmq_ctx_destroy (context);
        return 0;
    }

    Server:

    #include "../zhelpers.h"
    #include <pthread.h>
    #include <unistd.h>
    
    #include <sys/syscall.h>
    
    #define gettidv1() syscall(__NR_gettid)
    static void *
    worker_routine (void *context) {
        //  Socket to talk to dispatcher
        void *receiver = zmq_socket (context, ZMQ_REP);
        zmq_connect (receiver, "inproc://workers");
    
        while (1) {
            char *string = s_recv (receiver);
            printf ("[%ld]Received request: [%s]
    ",(long int)gettidv1(), string);
            free (string);
            //  Do some 'work'
            sleep (1);
            //  Send reply back to client
            s_send (receiver, "World");
        }
        zmq_close (receiver);
        return NULL;
    }
    
    int main (void)
    {
        void *context = zmq_ctx_new ();
    
        //  Socket to talk to clients
        void *clients = zmq_socket (context, ZMQ_ROUTER);
        zmq_bind (clients, "tcp://*:5555");
    
        //  Socket to talk to workers
        void *workers = zmq_socket (context, ZMQ_DEALER);
        zmq_bind (workers, "inproc://workers");
    
        //  Launch pool of worker threads
        int thread_nbr;
        for (thread_nbr = 0; thread_nbr < 5; thread_nbr++) {
            pthread_t worker;
            pthread_create (&worker, NULL, worker_routine, context);
        }
        //  Connect work threads to client threads via a queue proxy
        zmq_proxy (clients, workers, NULL);
    
        //  We never get here, but clean up anyhow
        zmq_close (clients);
        zmq_close (workers);
        zmq_ctx_destroy (context);
        return 0;
    }

    Out:

    // client
    Received reply 0 [World]
    Received reply 1 [World]
    Received reply 2 [World]
    Received reply 3 [World]
    Received reply 4 [World]
    Received reply 5 [World]
    Received reply 6 [World]
    Received reply 7 [World]
    Received reply 8 [World]
    Received reply 9 [World]
    
    // server
    [17403]Received request: [Hello 0]
    [17402]Received request: [Hello 1]
    [17404]Received request: [Hello 2]
    [17406]Received request: [Hello 3]
    [17405]Received request: [Hello 4]
    [17403]Received request: [Hello 5]
    [17402]Received request: [Hello 6]
    [17404]Received request: [Hello 7]
    [17406]Received request: [Hello 8]
    [17405]Received request: [Hello 9]

    代码还是简单的。

    • 服务端启动一组worker线程,每个worker创建一个REP套接字,并处理收到的请求。worker线程就像是一个单线程的服务,唯一的区别是使用了inproc而非tcp协议,以及绑定-连接的方向调换了。
    • 服务端创建ROUTER套接字用以和client通信,因此提供了一个TCP协议的外部接口。
    • 服务端创建DEALER套接字用以和worker通信,使用了内部接口(inproc)。
    • 服务端启动了QUEUE内部装置,连接两个端点上的套接字。QUEUE装置会将收到的请求分发给连接上的worker,并将应答路由给请求方。

  • 相关阅读:
    Android SwitchButton(滑动开关)
    创建您自己的Maven模板
    Bag标签成一条线的代码来实现中国字
    rabbitmq的java简单的实现
    【七】注入框架RoboGuice使用:(Your First Custom Binding)
    Sqlmap渗透测试是常用语句
    Android NOtification 使用(震动 闪屏 铃声)
    Android loader 详解
    Android实现获取本机中所有图片
    Android保存图片到系统图库
  • 原文地址:https://www.cnblogs.com/vczf/p/12874270.html
Copyright © 2011-2022 走看看