int XS_TEST_MAIN () { fprintf (stderr, "msg_flags test running...\n"); // Create the infrastructure void *ctx = xs_init (); assert (ctx); void *sb = xs_socket (ctx, XS_XREP); assert (sb); int rc = xs_bind (sb, "inproc://a"); assert (rc == 0); void *sc = xs_socket (ctx, XS_XREQ); assert (sc); rc = xs_connect (sc, "inproc://a"); assert (rc == 0); // Send 2-part message. rc = xs_send (sc, "A", 1, XS_SNDMORE); assert (rc == 1); rc = xs_send (sc, "B", 1, 0); assert (rc == 1); // Identity comes first. xs_msg_t msg; rc = xs_msg_init (&msg); assert (rc == 0); rc = xs_recvmsg (sb, &msg, 0); assert (rc >= 0); int more; size_t more_size = sizeof (more); rc = xs_getmsgopt (&msg, XS_MORE, &more, &more_size); assert (rc == 0); assert (more == 1); // Then the first part of the message body. rc = xs_recvmsg (sb, &msg, 0); assert (rc == 1); more_size = sizeof (more); rc = xs_getmsgopt (&msg, XS_MORE, &more, &more_size); assert (rc == 0); assert (more == 1); // And finally, the second part of the message body. rc = xs_recvmsg (sb, &msg, 0); assert (rc == 1); more_size = sizeof (more); rc = xs_getmsgopt (&msg, XS_MORE, &more, &more_size); assert (rc == 0); assert (more == 0); // Deallocate the infrastructure. rc = xs_close (sc); assert (rc == 0); rc = xs_close (sb); assert (rc == 0); rc = xs_term (ctx); assert (rc == 0); return 0 ; }
static void *worker (void *ctx_) #endif { void *s; int rc; int i; xs_msg_t msg; s = xs_socket (ctx_, XS_REP); if (!s) { printf ("error in xs_socket: %s\n", xs_strerror (errno)); exit (1); } rc = xs_connect (s, "inproc://lat_test"); if (rc == -1) { printf ("error in xs_connect: %s\n", xs_strerror (errno)); exit (1); } rc = xs_msg_init (&msg); if (rc != 0) { printf ("error in xs_msg_init: %s\n", xs_strerror (errno)); exit (1); } for (i = 0; i != roundtrip_count; i++) { rc = xs_recvmsg (s, &msg, 0); if (rc < 0) { printf ("error in xs_recvmsg: %s\n", xs_strerror (errno)); exit (1); } rc = xs_sendmsg (s, &msg, 0); if (rc < 0) { printf ("error in xs_sendmsg: %s\n", xs_strerror (errno)); exit (1); } } rc = xs_msg_close (&msg); if (rc != 0) { printf ("error in xs_msg_close: %s\n", xs_strerror (errno)); exit (1); } rc = xs_close (s); if (rc != 0) { printf ("error in xs_close: %s\n", xs_strerror (errno)); exit (1); } #if defined XS_HAVE_WINDOWS return 0; #else return NULL; #endif }
int zmq_msg_init (zmq_msg_t *msg) { xs_msg_t *content = (xs_msg_t*) malloc (sizeof (xs_msg_t)); assert (content); int rc = xs_msg_init (content); if (rc != 0) return -1; msg->content = (void*) content; return 0; }
int xs_sock_send (xs_sock *self, const void *buf, size_t len, int flags) { int rc; /* Convert buffer into a message. */ xs_msg msg; rc = xs_msg_init (&msg, len); if (rc < 0) return rc; memcpy (xs_msg_data (&msg), buf, len); xs_mutex_lock (&self->sync); while (1) { /* Start the send operation. */ rc = xs_tcpout_send (&self->out, &msg); /* If send succeeded synchronously, we can return immediately. */ if (likely (rc == 0)) { xs_mutex_unlock (&self->sync); return (int) len; } /* If the asynchronous send operation is pending, we can return immediately, however, we have to mark the connection is not writeable at the moment. */ if (rc == -EINPROGRESS) { xs_mutex_unlock (&self->sync); return (int) len; } /* In send is non-blocking and we cannot send, return to the caller. */ xs_assert (rc == -EAGAIN); if (flags & XS_DONTWAIT) { xs_mutex_unlock (&self->sync); return -EAGAIN; } /* Wait till socket becomes writeable. */ rc = pthread_cond_wait (&self->writeable, &self->sync); errnum_assert (rc); } }
int main (int argc, char *argv []) { const char *bind_to; int message_count; size_t message_size; void *ctx; void *s; int rc; int i; xs_msg_t msg; void *watch; unsigned long elapsed; unsigned long throughput; double megabits; if (argc != 4) { printf ("usage: local_thr <bind-to> <message-size> <message-count>\n"); return 1; } bind_to = argv [1]; message_size = atoi (argv [2]); message_count = atoi (argv [3]); ctx = xs_init (); if (!ctx) { printf ("error in xs_init: %s\n", xs_strerror (errno)); return -1; } s = xs_socket (ctx, XS_PULL); if (!s) { printf ("error in xs_socket: %s\n", xs_strerror (errno)); return -1; } // Add your socket options here. // For example XS_RATE, XS_RECOVERY_IVL and XS_MCAST_LOOP for PGM. rc = xs_bind (s, bind_to); if (rc == -1) { printf ("error in xs_bind: %s\n", xs_strerror (errno)); return -1; } rc = xs_msg_init (&msg); if (rc != 0) { printf ("error in xs_msg_init: %s\n", xs_strerror (errno)); return -1; } rc = xs_recvmsg (s, &msg, 0); if (rc < 0) { printf ("error in xs_recvmsg: %s\n", xs_strerror (errno)); return -1; } if (xs_msg_size (&msg) != message_size) { printf ("message of incorrect size received\n"); return -1; } watch = xs_stopwatch_start (); for (i = 0; i != message_count - 1; i++) { rc = xs_recvmsg (s, &msg, 0); if (rc < 0) { printf ("error in xs_recvmsg: %s\n", xs_strerror (errno)); return -1; } if (xs_msg_size (&msg) != message_size) { printf ("message of incorrect size received\n"); return -1; } } elapsed = xs_stopwatch_stop (watch); if (elapsed == 0) elapsed = 1; rc = xs_msg_close (&msg); if (rc != 0) { printf ("error in xs_msg_close: %s\n", xs_strerror (errno)); return -1; } throughput = (unsigned long) ((double) message_count / (double) elapsed * 1000000); megabits = (double) (throughput * message_size * 8) / 1000000; printf ("message size: %d [B]\n", (int) message_size); printf ("message count: %d\n", (int) message_count); printf ("mean throughput: %d [msg/s]\n", (int) throughput); printf ("mean throughput: %.3f [Mb/s]\n", (double) megabits); rc = xs_close (s); if (rc != 0) { printf ("error in xs_close: %s\n", xs_strerror (errno)); return -1; } rc = xs_term (ctx); if (rc != 0) { printf ("error in xs_term: %s\n", xs_strerror (errno)); return -1; } return 0; }
int zmq_device (int device, void *frontend, void *backend) { int more; size_t size; xs_msg_t msg; xs_pollitem_t items [2]; int rc = xs_msg_init (&msg); if (rc != 0) return -1; items [0].socket = frontend; items [0].events = XS_POLLIN; items [1].socket = backend; items [1].events = XS_POLLIN; while (1) { rc = xs_poll (&items [0], 2, -1); if (rc < 0) return -1; if (items [0].revents & XS_POLLIN) { while (1) { rc = xs_recvmsg (frontend, &msg, 0); if (rc < 0) return -1; size = sizeof (more); rc = xs_getsockopt (frontend, XS_RCVMORE, &more, &size); if (rc < 0) return -1; rc = xs_sendmsg (backend, &msg, more ? XS_SNDMORE : 0); if (rc < 0) return -1; if (!more) break; } } if (items [1].revents & XS_POLLIN) { while (1) { rc = xs_recvmsg (backend, &msg, 0); if (rc < 0) return -1; size = sizeof (more); rc = xs_getsockopt (backend, XS_RCVMORE, &more, &size); if (rc < 0) return -1; rc = xs_sendmsg (frontend, &msg, more ? ZMQ_SNDMORE : 0); if (rc < 0) return -1; if (!more) break; } } } return 0; }
nmsg_res _input_nmsg_read_container_xs(nmsg_input_t input, Nmsg__Nmsg **nmsg) { int ret; nmsg_res res; uint8_t *buf; size_t buf_len; ssize_t msgsize = 0; xs_msg_t xmsg; xs_pollitem_t xitems[1]; /* poll */ xitems[0].socket = input->stream->xs; xitems[0].events = XS_POLLIN; ret = xs_poll(xitems, 1, NMSG_RBUF_TIMEOUT); if (ret == 0 || (ret == -1 && errno == EINTR)) return (nmsg_res_again); else if (ret == -1) return (nmsg_res_read_failure); /* initialize XS message object */ if (xs_msg_init(&xmsg)) return (nmsg_res_failure); /* read the NMSG container */ if (xs_recvmsg(input->stream->xs, &xmsg, 0) == -1) { res = nmsg_res_failure; goto out; } nmsg_timespec_get(&input->stream->now); /* get buffer from the XS message */ buf = xs_msg_data(&xmsg); buf_len = xs_msg_size(&xmsg); if (buf_len < NMSG_HDRLSZ_V2) { res = nmsg_res_failure; goto out; } /* deserialize the NMSG header */ res = _input_nmsg_deserialize_header(buf, buf_len, &msgsize, &input->stream->flags); if (res != nmsg_res_success) goto out; buf += NMSG_HDRLSZ_V2; /* the entire message must have been read by xs_recvmsg() */ assert((size_t) msgsize == buf_len - NMSG_HDRLSZ_V2); /* unpack message */ res = _input_nmsg_unpack_container(input, nmsg, buf, msgsize); /* update seqsrc counts */ if (input->stream->verify_seqsrc && *nmsg != NULL) { struct nmsg_seqsrc *seqsrc = _input_seqsrc_get(input, *nmsg); if (seqsrc != NULL) _input_seqsrc_update(input, seqsrc, *nmsg); } /* expire old outstanding fragments */ _input_frag_gc(input->stream); out: xs_msg_close(&xmsg); return (res); }
int XS_TEST_MAIN () { fprintf (stderr, "reqrep_device test running...\n"); void *ctx = xs_init (); errno_assert (ctx); // Create a req/rep device. void *xreq = xs_socket (ctx, XS_XREQ); errno_assert (xreq); int rc = xs_bind (xreq, "tcp://127.0.0.1:5560"); errno_assert (rc != -1); void *xrep = xs_socket (ctx, XS_XREP); errno_assert (xrep); rc = xs_bind (xrep, "tcp://127.0.0.1:5561"); errno_assert (rc != -1); // Create a worker. void *rep = xs_socket (ctx, XS_REP); errno_assert (rep); rc = xs_connect (rep, "tcp://127.0.0.1:5560"); errno_assert (rc != -1); // Create a client. void *req = xs_socket (ctx, XS_REQ); errno_assert (req); rc = xs_connect (req, "tcp://127.0.0.1:5561"); errno_assert (rc != -1); // Send a request. rc = xs_send (req, "ABC", 3, XS_SNDMORE); errno_assert (rc == 3); rc = xs_send (req, "DEF", 3, 0); errno_assert (rc == 3); // Pass the request through the device. for (int i = 0; i != 4; i++) { xs_msg_t msg; rc = xs_msg_init (&msg); errno_assert (rc == 0); rc = xs_recvmsg (xrep, &msg, 0); errno_assert (rc >= 0); int rcvmore; size_t sz = sizeof (rcvmore); rc = xs_getsockopt (xrep, XS_RCVMORE, &rcvmore, &sz); errno_assert (rc == 0); rc = xs_sendmsg (xreq, &msg, rcvmore ? XS_SNDMORE : 0); errno_assert (rc >= 0); } // Receive the request. char buff [3]; rc = xs_recv (rep, buff, 3, 0); errno_assert (rc == 3); assert (memcmp (buff, "ABC", 3) == 0); int rcvmore; size_t sz = sizeof (rcvmore); rc = xs_getsockopt (rep, XS_RCVMORE, &rcvmore, &sz); errno_assert (rc == 0); assert (rcvmore); rc = xs_recv (rep, buff, 3, 0); errno_assert (rc == 3); assert (memcmp (buff, "DEF", 3) == 0); rc = xs_getsockopt (rep, XS_RCVMORE, &rcvmore, &sz); errno_assert (rc == 0); assert (!rcvmore); // Send the reply. rc = xs_send (rep, "GHI", 3, XS_SNDMORE); errno_assert (rc == 3); rc = xs_send (rep, "JKL", 3, 0); errno_assert (rc == 3); // Pass the reply through the device. for (int i = 0; i != 4; i++) { xs_msg_t msg; rc = xs_msg_init (&msg); errno_assert (rc == 0); rc = xs_recvmsg (xreq, &msg, 0); errno_assert (rc >= 0); rc = xs_getsockopt (xreq, XS_RCVMORE, &rcvmore, &sz); errno_assert (rc == 0); rc = xs_sendmsg (xrep, &msg, rcvmore ? XS_SNDMORE : 0); errno_assert (rc >= 0); } // Receive the reply. rc = xs_recv (req, buff, 3, 0); errno_assert (rc == 3); assert (memcmp (buff, "GHI", 3) == 0); rc = xs_getsockopt (req, XS_RCVMORE, &rcvmore, &sz); errno_assert (rc == 0); assert (rcvmore); rc = xs_recv (req, buff, 3, 0); errno_assert (rc == 3); assert (memcmp (buff, "JKL", 3) == 0); rc = xs_getsockopt (req, XS_RCVMORE, &rcvmore, &sz); errno_assert (rc == 0); assert (!rcvmore); // Clean up. rc = xs_close (req); errno_assert (rc == 0); rc = xs_close (rep); errno_assert (rc == 0); rc = xs_close (xrep); errno_assert (rc == 0); rc = xs_close (xreq); errno_assert (rc == 0); rc = xs_term (ctx); errno_assert (rc == 0); return 0 ; }
int main (int argc, char *argv []) { #if defined XS_HAVE_WINDOWS HANDLE local_thread; #else pthread_t local_thread; #endif void *ctx; void *s; int rc; int i; xs_msg_t msg; void *watch; unsigned long elapsed; unsigned long throughput; double megabits; if (argc != 3) { printf ("usage: thread_thr <message-size> <message-count>\n"); return 1; } message_size = atoi (argv [1]); message_count = atoi (argv [2]); ctx = xs_init (); if (!ctx) { printf ("error in xs_init: %s\n", xs_strerror (errno)); return -1; } s = xs_socket (ctx, XS_PULL); if (!s) { printf ("error in xs_socket: %s\n", xs_strerror (errno)); return -1; } rc = xs_bind (s, "inproc://thr_test"); if (rc == -1) { printf ("error in xs_bind: %s\n", xs_strerror (errno)); return -1; } #if defined XS_HAVE_WINDOWS local_thread = (HANDLE) _beginthreadex (NULL, 0, worker, ctx, 0 , NULL); if (local_thread == 0) { printf ("error in _beginthreadex\n"); return -1; } #else rc = pthread_create (&local_thread, NULL, worker, ctx); if (rc != 0) { printf ("error in pthread_create: %s\n", xs_strerror (rc)); return -1; } #endif rc = xs_msg_init (&msg); if (rc != 0) { printf ("error in xs_msg_init: %s\n", xs_strerror (errno)); return -1; } printf ("message size: %d [B]\n", (int) message_size); printf ("message count: %d\n", (int) message_count); rc = xs_recvmsg (s, &msg, 0); if (rc < 0) { printf ("error in xs_recvmsg: %s\n", xs_strerror (errno)); return -1; } if (xs_msg_size (&msg) != message_size) { printf ("message of incorrect size received\n"); return -1; } watch = xs_stopwatch_start (); for (i = 0; i != message_count - 1; i++) { rc = xs_recvmsg (s, &msg, 0); if (rc < 0) { printf ("error in xs_recvmsg: %s\n", xs_strerror (errno)); return -1; } if (xs_msg_size (&msg) != message_size) { printf ("message of incorrect size received\n"); return -1; } } elapsed = xs_stopwatch_stop (watch); if (elapsed == 0) elapsed = 1; rc = xs_msg_close (&msg); if (rc != 0) { printf ("error in xs_msg_close: %s\n", xs_strerror (errno)); return -1; } #if defined XS_HAVE_WINDOWS DWORD rc2 = WaitForSingleObject (local_thread, INFINITE); if (rc2 == WAIT_FAILED) { printf ("error in WaitForSingleObject\n"); return -1; } BOOL rc3 = CloseHandle (local_thread); if (rc3 == 0) { printf ("error in CloseHandle\n"); return -1; } #else rc = pthread_join (local_thread, NULL); if (rc != 0) { printf ("error in pthread_join: %s\n", xs_strerror (rc)); return -1; } #endif rc = xs_close (s); if (rc != 0) { printf ("error in xs_close: %s\n", xs_strerror (errno)); return -1; } rc = xs_term (ctx); if (rc != 0) { printf ("error in xs_term: %s\n", xs_strerror (errno)); return -1; } throughput = (unsigned long) ((double) message_count / (double) elapsed * 1000000); megabits = (double) (throughput * message_size * 8) / 1000000; printf ("mean throughput: %d [msg/s]\n", (int) throughput); printf ("mean throughput: %.3f [Mb/s]\n", (double) megabits); return 0; }
int xs_instream_recv (xs_instream *self, xs_msg *msg) { int rc; ssize_t nbytes; /* If there's a message available, return is straight away. */ if (self->state == 2) { xs_msg_move (msg, &self->msg); self->state = 0; return 0; } /* If message is being asynchronously received at the moment, there's no message to return yet. */ if (self->state == 1) return -EINPROGRESS; /* Try to read the message in a synchronous way. */ nbytes = recv (self->fd, self->sizebuf, 8, MSG_DONTWAIT); /* Sanitation of the result. */ if (unlikely (nbytes == 0)) { errno = ECONNREFUSED; nbytes = -1; } else if (unlikely (nbytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))) nbytes = 0; errno_assert (nbytes >= 0); if (nbytes < 8) { self->recvd = nbytes; /* TODO: xs_instream_launch_async (self); */ return -EINPROGRESS; } rc = xs_msg_init (&self->msg, xs_getll (self->sizebuf)); err_assert (rc); nbytes = recv (self->fd, xs_msg_data (&self->msg), xs_msg_size (&self->msg), MSG_DONTWAIT); /* Sanitation of the result. */ if (unlikely (nbytes == 0)) { errno = ECONNREFUSED; nbytes = -1; } else if (unlikely (nbytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))) nbytes = 0; if (nbytes < xs_msg_size (&self->msg)) { self->recvd = nbytes + 8; /* TODO: xs_instream_launch_async (self); */ return -EINPROGRESS; } /* Synchronous receive was successful. */ xs_msg_move (msg, &self->msg); return 0; }