zeromq client-server 异步模式

View Code
  1 //
  2  //   Asynchronous client-to-server (DEALER to ROUTER)
  3  //
  4  //   While this example runs in a single process, that is just to make
  5  //   it easier to start and stop the example. Each task has its own
  6  //   context and conceptually acts as a separate process.
  7  
  8 #include "czmq.h"
  9  
 10 //  ---------------------------------------------------------------------
 11  //   This is our client task
 12  //   It connects to the server, and then sends a request once per second
 13  //   It collects responses as they arrive, and it prints them out. We will
 14  //   run several client tasks in parallel, each with a different random ID.
 15  
 16 static void *
 17  client_task (void *args)
 18  {
 19      zctx_t *ctx = zctx_new ();
 20      void *client = zsocket_new (ctx, ZMQ_DEALER);
 21  
 22     //   Set random identity to make tracing easier
 23      char identity [10];
 24      sprintf (identity, "%04X-%04X", randof (0x10000), randof (0x10000));
 25      zsockopt_set_identity (client, identity);
 26      zsocket_connect (client, "tcp://localhost:5570");
 27  
 28     zmq_pollitem_t items [] = { { client, 0, ZMQ_POLLIN, 0 } };
 29      int request_nbr = 0;
 30      while (1) {
 31          //   Tick once per second, pulling in arriving messages
 32          int centitick;
 33          for (centitick = 0; centitick < 100; centitick++) {
 34              zmq_poll (items, 1, 10 * ZMQ_POLL_MSEC);
 35              if (items [0].revents & ZMQ_POLLIN) {
 36                  zmsg_t *msg = zmsg_recv (client);
 37                  zframe_print (zmsg_last (msg), identity);
 38                  zmsg_destroy (&msg);
 39              }
 40          }
 41          zstr_sendf (client, "request #%d", ++request_nbr);
 42      }
 43      zctx_destroy (&ctx);
 44      return NULL;
 45  }
 46  
 47 //   This is our server task.
 48  //   It uses the multithreaded server model to deal requests out to a pool
 49  //   of workers and route replies back to clients. One worker can handle
 50  //   one request at a time but one client can talk to multiple workers at
 51  //   once.
 52  
 53 static void server_worker (void *args, zctx_t *ctx, void *pipe);
 54  
 55 void *server_task (void *args)
 56  {
 57      zctx_t *ctx = zctx_new ();
 58  
 59     //   Frontend socket talks to clients over TCP
 60      void *frontend = zsocket_new (ctx, ZMQ_ROUTER);
 61      zsocket_bind (frontend, "tcp://*:5570");
 62  
 63     //   Backend socket talks to workers over inproc
 64      void *backend = zsocket_new (ctx, ZMQ_DEALER);
 65      zsocket_bind (backend, "inproc://backend");
 66  
 67     //   Launch pool of worker threads, precise number is not critical
 68      int thread_nbr;
 69      for (thread_nbr = 0; thread_nbr < 5; thread_nbr++)
 70          zthread_fork (ctx, server_worker, NULL);
 71  
 72     //   Connect backend to frontend via a queue device
 73      //   We could do this:
 74      //       zmq_device (ZMQ_QUEUE, frontend, backend);
 75      //   But doing it ourselves means we can debug this more easily
 76  
 77     //   Switch messages between frontend and backend
 78      while (1) {
 79          zmq_pollitem_t items [] = {
 80              { frontend, 0, ZMQ_POLLIN, 0 },
 81              { backend,   0, ZMQ_POLLIN, 0 }
 82          };
 83          zmq_poll (items, 2, -1);
 84          if (items [0].revents & ZMQ_POLLIN) {
 85              zmsg_t *msg = zmsg_recv (frontend);
 86              zmsg_send (&msg, backend);
 87          }
 88          if (items [1].revents & ZMQ_POLLIN) {
 89              zmsg_t *msg = zmsg_recv (backend);
 90              zmsg_send (&msg, frontend);
 91          }
 92      }
 93      zctx_destroy (&ctx);
 94      return NULL;
 95  }
 96  
 97 //   Each worker task works on one request at a time and sends a random number
 98  //   of replies back, with random delays between replies:
 99  
100 static void
101  server_worker (void *args, zctx_t *ctx, void *pipe)
102  {
103      void *worker = zsocket_new (ctx, ZMQ_DEALER);
104      zsocket_connect (worker, "inproc://backend");
105  
106     while (1) {
107          //   The DEALER socket gives us the address envelope and message
108          zmsg_t *msg = zmsg_recv (worker);
109          zframe_t *address = zmsg_pop (msg);
110          zframe_t *content = zmsg_pop (msg);
111          assert (content);
112          zmsg_destroy (&msg);
113  
114         //   Send 0..4 replies back
115          int reply, replies = randof (5);
116          for (reply = 0; reply < replies; reply++) {
117              //   Sleep for some fraction of a second
118              zclock_sleep (randof (1000) + 1);
119              zframe_send (&address, worker, ZFRAME_REUSE + ZFRAME_MORE);
120              zframe_send (&content, worker, ZFRAME_REUSE);
121          }
122          zframe_destroy (&address);
123          zframe_destroy (&content);
124      }
125  }
126  
127 //   The main thread simply starts several clients, and a server, and then
128  //   waits for the server to finish.
129  
130 int main (void)
131  {
132      zctx_t *ctx = zctx_new ();
133      zthread_new (client_task, NULL);
134      zthread_new (client_task, NULL);
135      zthread_new (client_task, NULL);
136      zthread_new (server_task, NULL);
137  
138     //   Run for 5 seconds then quit
139      zclock_sleep (5 * 1000);
140      zctx_destroy (&ctx);
141      return 0;
142  }

 fig45.png

posted @ 2012-10-06 16:42  追心  阅读(2388)  评论(0编辑  收藏  举报