mlm_msg_t * mlm_msg_link (mlm_msg_t *self) { assert (self); zmq_atomic_counter_inc (self->refcount); return self; }
static void client_task (void *db) { struct thread_data *databag = (struct thread_data *)db; // Endpoint socket gets random port to avoid test failing when port in use void *endpoint = zmq_socket (databag->ctx, ZMQ_PAIR); assert (endpoint); int linger = 0; int rc = zmq_setsockopt (endpoint, ZMQ_LINGER, &linger, sizeof (linger)); assert (rc == 0); char endpoint_source [256]; sprintf (endpoint_source, "inproc://endpoint%d", databag->id); rc = zmq_connect (endpoint, endpoint_source); assert (rc == 0); char *my_endpoint = s_recv (endpoint); assert (my_endpoint); void *client = zmq_socket (databag->ctx, ZMQ_DEALER); assert (client); // Control socket receives terminate command from main over inproc void *control = zmq_socket (databag->ctx, ZMQ_SUB); assert (control); rc = zmq_setsockopt (control, ZMQ_SUBSCRIBE, "", 0); assert (rc == 0); rc = zmq_setsockopt (control, ZMQ_LINGER, &linger, sizeof (linger)); assert (rc == 0); rc = zmq_connect (control, "inproc://control"); assert (rc == 0); char content [CONTENT_SIZE_MAX]; // Set random routing id to make tracing easier char routing_id [ROUTING_ID_SIZE]; sprintf (routing_id, "%04X-%04X", rand() % 0xFFFF, rand() % 0xFFFF); rc = zmq_setsockopt (client, ZMQ_ROUTING_ID, routing_id, ROUTING_ID_SIZE); // includes '\0' as an helper for printf assert (rc == 0); linger = 0; rc = zmq_setsockopt (client, ZMQ_LINGER, &linger, sizeof (linger)); assert (rc == 0); rc = zmq_connect (client, my_endpoint); assert (rc == 0); zmq_pollitem_t items [] = { { client, 0, ZMQ_POLLIN, 0 }, { control, 0, ZMQ_POLLIN, 0 } }; int request_nbr = 0; bool run = true; bool keep_sending = true; while (run) { // Tick once per 200 ms, pulling in arriving messages int centitick; for (centitick = 0; centitick < 20; centitick++) { zmq_poll (items, 2, 10); if (items [0].revents & ZMQ_POLLIN) { int rcvmore; size_t sz = sizeof (rcvmore); rc = zmq_recv (client, content, CONTENT_SIZE_MAX, 0); assert (rc == CONTENT_SIZE); if (is_verbose) printf("client receive - routing_id = %s content = %s\n", routing_id, content); // Check that message is still the same assert (memcmp (content, "request #", 9) == 0); rc = zmq_getsockopt (client, ZMQ_RCVMORE, &rcvmore, &sz); assert (rc == 0); assert (!rcvmore); } if (items [1].revents & ZMQ_POLLIN) { rc = zmq_recv (control, content, CONTENT_SIZE_MAX, 0); if (rc > 0) { content[rc] = 0; // NULL-terminate the command string if (is_verbose) printf("client receive - routing_id = %s command = %s\n", routing_id, content); if (memcmp (content, "TERMINATE", 9) == 0) { run = false; break; } if (memcmp (content, "STOP", 4) == 0) { keep_sending = false; break; } } } } if (keep_sending) { sprintf(content, "request #%03d", ++request_nbr); // CONTENT_SIZE if (is_verbose) printf("client send - routing_id = %s request #%03d\n", routing_id, request_nbr); zmq_atomic_counter_inc(g_clients_pkts_out); rc = zmq_send (client, content, CONTENT_SIZE, 0); assert (rc == CONTENT_SIZE); } } rc = zmq_close (client); assert (rc == 0); rc = zmq_close (control); assert (rc == 0); rc = zmq_close (endpoint); assert (rc == 0); free (my_endpoint); }
static void server_worker (void *ctx) { void *worker = zmq_socket (ctx, ZMQ_DEALER); assert (worker); int linger = 0; int rc = zmq_setsockopt (worker, ZMQ_LINGER, &linger, sizeof (linger)); assert (rc == 0); rc = zmq_connect (worker, "inproc://backend"); assert (rc == 0); // Control socket receives terminate command from main over inproc void *control = zmq_socket (ctx, ZMQ_SUB); assert (control); rc = zmq_setsockopt (control, ZMQ_SUBSCRIBE, "", 0); assert (rc == 0); rc = zmq_setsockopt (control, ZMQ_LINGER, &linger, sizeof (linger)); assert (rc == 0); rc = zmq_connect (control, "inproc://control"); assert (rc == 0); char content [CONTENT_SIZE_MAX]; // bigger than what we need to check that char routing_id [ROUTING_ID_SIZE_MAX]; // the size received is the size sent bool run = true; bool keep_sending = true; while (run) { rc = zmq_recv (control, content, CONTENT_SIZE_MAX, ZMQ_DONTWAIT); // usually, rc == -1 (no message) if (rc > 0) { content[rc] = 0; // NULL-terminate the command string if (is_verbose) printf("server_worker receives command = %s\n", content); if (memcmp (content, "TERMINATE", 9) == 0) run = false; if (memcmp (content, "STOP", 4) == 0) keep_sending = false; } // The DEALER socket gives us the reply envelope and message // if we don't poll, we have to use ZMQ_DONTWAIT, if we poll, we can block-receive with 0 rc = zmq_recv (worker, routing_id, ROUTING_ID_SIZE_MAX, ZMQ_DONTWAIT); if (rc == ROUTING_ID_SIZE) { rc = zmq_recv (worker, content, CONTENT_SIZE_MAX, 0); assert (rc == CONTENT_SIZE); if (is_verbose) printf ("server receive - routing_id = %s content = %s\n", routing_id, content); // Send 0..4 replies back if (keep_sending) { int reply, replies = rand() % 5; for (reply = 0; reply < replies; reply++) { // Sleep for some fraction of a second msleep (rand () % 10 + 1); // Send message from server to client if (is_verbose) printf("server send - routing_id = %s reply\n", routing_id); zmq_atomic_counter_inc(g_workers_pkts_out); rc = zmq_send (worker, routing_id, ROUTING_ID_SIZE, ZMQ_SNDMORE); assert (rc == ROUTING_ID_SIZE); rc = zmq_send (worker, content, CONTENT_SIZE, 0); assert (rc == CONTENT_SIZE); } } } } rc = zmq_close (worker); assert (rc == 0); rc = zmq_close (control); assert (rc == 0); }