void server_task (void *ctx) { // Frontend socket talks to main process void *frontend = zmq_socket (ctx, ZMQ_SUB); assert (frontend); int rc = zmq_setsockopt (frontend, ZMQ_SUBSCRIBE, "", 0); assert (rc == 0); rc = zmq_bind (frontend, "tcp://127.0.0.1:15564"); assert (rc == 0); // Nice socket which is never read void *backend = zmq_socket (ctx, ZMQ_PUSH); assert (backend); rc = zmq_bind (backend, "tcp://127.0.0.1:15563"); 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_connect (control, "inproc://control"); assert (rc == 0); // Connect backend to frontend via a proxy zmq_proxy_steerable (frontend, backend, NULL, control); rc = zmq_close (frontend); assert (rc == 0); rc = zmq_close (backend); assert (rc == 0); rc = zmq_close (control); assert (rc == 0); }
inline void proxy_steerable(void *frontend, void *backend, void *capture, void *control) { int rc = zmq_proxy_steerable(frontend, backend, capture, control); if (rc != 0) throw error_t(); }
void server_task (void *ctx) { // Frontend socket talks to clients over TCP void *frontend = zmq_socket (ctx, ZMQ_ROUTER); assert (frontend); int rc = zmq_bind (frontend, "tcp://127.0.0.1:5563"); assert (rc == 0); // Backend socket talks to workers over inproc void *backend = zmq_socket (ctx, ZMQ_DEALER); assert (backend); rc = zmq_bind (backend, "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_connect (control, "inproc://control"); assert (rc == 0); // Launch pool of worker threads, precise number is not critical int thread_nbr; void* threads [5]; for (thread_nbr = 0; thread_nbr < QT_WORKERS; thread_nbr++) threads[thread_nbr] = zmq_threadstart (&server_worker, ctx); // Connect backend to frontend via a proxy zmq_proxy_steerable (frontend, backend, NULL, control); for (thread_nbr = 0; thread_nbr < QT_WORKERS; thread_nbr++) zmq_threadclose (threads[thread_nbr]); rc = zmq_close (frontend); assert (rc == 0); rc = zmq_close (backend); assert (rc == 0); rc = zmq_close (control); assert (rc == 0); }
// Call from work to establish a proxy between two sockets. void worker::relay(socket& left, socket& right) { // Blocks until the context is terminated, always returns -1. zmq_proxy_steerable(left.self(), right.self(), nullptr, nullptr); // Equivalent implementation: ////zmq::poller poller; ////poller.add(left); ////poller.add(right); //// ////while (!poller.terminated()) ////{ //// const auto signaled = poller.wait(); //// //// if (signaled.contains(left.id())) //// forward(left, right); //// //// if (signaled.contains(right.id())) //// forward(right, left); ////} }
void server_task (void *ctx) { void *rep = zmq_socket (ctx, ZMQ_REP); assert (rep); int rc = zmq_bind (rep, "tcp://127.0.0.1:5563"); 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_connect (control, "inproc://control"); assert (rc == 0); // Use rep as both frontend and backend zmq_proxy_steerable (rep, rep, NULL, control); rc = zmq_close (rep); assert (rc == 0); rc = zmq_close (control); assert (rc == 0); }
void server_task (void *ctx) { // Frontend socket talks to clients over TCP size_t len = MAX_SOCKET_STRING; char my_endpoint[MAX_SOCKET_STRING]; void *frontend = zmq_socket (ctx, ZMQ_ROUTER); assert (frontend); int linger = 0; int rc = zmq_setsockopt (frontend, ZMQ_LINGER, &linger, sizeof (linger)); assert (rc == 0); rc = zmq_bind (frontend, "tcp://127.0.0.1:*"); assert (rc == 0); rc = zmq_getsockopt (frontend, ZMQ_LAST_ENDPOINT, my_endpoint, &len); assert (rc == 0); // Backend socket talks to workers over inproc void *backend = zmq_socket (ctx, ZMQ_DEALER); assert (backend); rc = zmq_setsockopt (backend, ZMQ_LINGER, &linger, sizeof (linger)); assert (rc == 0); rc = zmq_bind (backend, "inproc://backend"); assert (rc == 0); // Control socket receives terminate command from main over inproc void *control = zmq_socket (ctx, ZMQ_REP); assert (control); rc = zmq_setsockopt (control, ZMQ_LINGER, &linger, sizeof (linger)); assert (rc == 0); rc = zmq_connect (control, "inproc://control_proxy"); assert (rc == 0); // Launch pool of worker threads, precise number is not critical int thread_nbr; void* threads [5]; for (thread_nbr = 0; thread_nbr < QT_WORKERS; thread_nbr++) threads[thread_nbr] = zmq_threadstart (&server_worker, ctx); // Endpoint socket sends random port to avoid test failing when port in use void *endpoint_receivers [QT_CLIENTS]; char endpoint_source [256]; for (int i = 0; i < QT_CLIENTS; ++i) { endpoint_receivers [i] = zmq_socket (ctx, ZMQ_PAIR); assert (endpoint_receivers [i]); rc = zmq_setsockopt (endpoint_receivers [i], ZMQ_LINGER, &linger, sizeof (linger)); assert (rc == 0); sprintf (endpoint_source, "inproc://endpoint%d", i); rc = zmq_bind (endpoint_receivers [i], endpoint_source); assert (rc == 0); } for (int i = 0; i < QT_CLIENTS; ++i) { rc = s_send (endpoint_receivers [i], my_endpoint); assert (rc > 0); } // Connect backend to frontend via a proxy rc = zmq_proxy_steerable (frontend, backend, NULL, control); assert (rc == 0); for (thread_nbr = 0; thread_nbr < QT_WORKERS; thread_nbr++) zmq_threadclose (threads[thread_nbr]); rc = zmq_close (frontend); assert (rc == 0); rc = zmq_close (backend); assert (rc == 0); rc = zmq_close (control); assert (rc == 0); for (int i = 0; i < QT_CLIENTS; ++i) { rc = zmq_close(endpoint_receivers [i]); assert (rc == 0); } }
static void proxy_thread_main (void *pvoid) { const proxy_hwm_cfg_t *cfg = (proxy_hwm_cfg_t *) pvoid; int rc; // FRONTEND SUB void *frontend_xsub = zmq_socket ( cfg->context, ZMQ_XSUB); // the frontend is the one exposed to internal threads (INPROC) assert (frontend_xsub); set_hwm (frontend_xsub); // Bind FRONTEND for (unsigned int i = 0; i < ARRAY_SIZE (cfg->frontend_endpoint); i++) { const char *ep = cfg->frontend_endpoint[i]; if (ep != NULL) { assert (strlen (ep) > 5); rc = zmq_bind (frontend_xsub, ep); assert (rc == 0); } } // BACKEND PUB void *backend_xpub = zmq_socket ( cfg->context, ZMQ_XPUB); // the backend is the one exposed to the external world (TCP) assert (backend_xpub); int optval = 1; rc = zmq_setsockopt (backend_xpub, ZMQ_XPUB_NODROP, &optval, sizeof (optval)); assert (rc == 0); set_hwm (backend_xpub); // Bind BACKEND for (unsigned int i = 0; i < ARRAY_SIZE (cfg->backend_endpoint); i++) { const char *ep = cfg->backend_endpoint[i]; if (ep != NULL) { assert (strlen (ep) > 5); rc = zmq_bind (backend_xpub, ep); assert (rc == 0); } } // CONTROL REP void *control_rep = zmq_socket ( cfg->context, ZMQ_REP); // This one is used by the proxy to receive&reply to commands assert (control_rep); // Bind CONTROL rc = zmq_bind (control_rep, cfg->control_endpoint); assert (rc == 0); // Start proxying! zmq_proxy_steerable (frontend_xsub, backend_xpub, NULL, control_rep); zmq_close (frontend_xsub); zmq_close (backend_xpub); zmq_close (control_rep); printf ("proxy thread ended\n"); }