[zeromq-dev] DEALER/REP problem

Whit Armstrong armstrong.whit at gmail.com
Fri Oct 14 16:28:16 CEST 2011


Thanks, Pieter.

I re-read ch2 and ch3 of the guide.  it's still not clear to me what
messaging pattern I need.

What I'm trying to do is take the standard
client(REQ)->queue(ROUTER/DEALER)<-worker(REP) pattern, but allow the
clients to use an asynchronous send so that the jobs can run in
parallel.

I've been able to get this idea to work using DEALER sockets across
the client, queue, and workers.
i.e.  client(DEALER)->queue(DEALER/DEALER)<-worker(DEALER)

However, if my understanding is correct, this design does not allow
multiple clients to use the workers simultaneously. Since the DEALER
socket will fair queue the results, if two clients submitted jobs
simultaneously, they would be at risk of receiving the other clients
results.

Can someone please help me understand this pattern a little better.
The code below is the DEALER's on all endpoints example from above.

Is my assumption correct, that if multiple clients connect, they would
be at risk of receiving a different client's results?

-Whit

server code:

void *worker_routine (void *arg)
{
  zmq::context_t *context = (zmq::context_t *) arg;

  zmq::socket_t socket (*context, ZMQ_DEALER);
  socket.connect ("inproc://workers");

  while (true) {
    zmq::message_t msg;
    socket.recv (&msg);
    int req_data;
    memcpy(&req_data,msg.data(),sizeof(int));
    double ans = req_data * 100;
    zmq::message_t rep(sizeof(double));
    memcpy(rep.data(),&ans,sizeof(double));
    //sleep(1);
    socket.send(rep);
  }
  return NULL;
}


int main ()
{
  //  Prepare our context and sockets
  zmq::context_t context (1);
  //zmq::socket_t clients (context, ZMQ_ROUTER); <-- does not work
  zmq::socket_t clients (context, ZMQ_DEALER);
  clients.bind ("tcp://*:5555");
  zmq::socket_t workers (context, ZMQ_DEALER);
  workers.bind ("inproc://workers");

  //  Launch pool of worker threads
  for (int thread_nbr = 0; thread_nbr != 5; thread_nbr++) {
    pthread_t worker;
    pthread_create (&worker, NULL, worker_routine, (void *) &context);
  }
  //  Connect work threads to client threads via a queue
  zmq::device (ZMQ_QUEUE, clients, workers);
  return 0;
}



client code:
int main () {
  const int N(10);
  //  Prepare our context and socket
  zmq::context_t context (1);
  zmq::socket_t socket (context, ZMQ_DEALER);

  cout << "Connecting to hello world server..." << endl;
  socket.connect ("tcp://localhost:5555");
  //  Do N requests, followed by N replies
  for (int i = 0; i < N; i++) {
    cout << "sending: " << i << endl;
    zmq::message_t request(sizeof(int));
    memcpy(request.data(),&i,sizeof(int));
    socket.send(request);
  }

  for (int i = 0; i < N; i++) {
    zmq::message_t rep;
    socket.recv(&rep);
    double result;
    memcpy(&result,rep.data(),sizeof(double));
    cout << "result: " << result << endl;
  }
  return 0;
}




On Thu, Oct 13, 2011 at 4:25 PM, Pieter Hintjens <ph at imatix.com> wrote:
> On Thu, Oct 13, 2011 at 2:55 PM, Whit Armstrong
> <armstrong.whit at gmail.com> wrote:
>
>> I thought DEALER/REP was a valid socket combo.  Do I need a ROUTER or
>> REQ somewhere in the chain to make REP happy?
>
> You can use DEALER / REP if you construct a proper envelope for the
> REP socket to work with. This is explained in the Guide, Ch2. It's a
> little tricky. The REP socket expects an envelope (0 or more frames)
> followed by a null frame, followed by the payload.
>
> -Pieter
> _______________________________________________
> zeromq-dev mailing list
> zeromq-dev at lists.zeromq.org
> http://lists.zeromq.org/mailman/listinfo/zeromq-dev
>



More information about the zeromq-dev mailing list