From fd6c89459e0f72c94c117c5a6084b4bdc539faaf Mon Sep 17 00:00:00 2001
From: gdamore nng_send or nng_sendmsg.
int nng_recv(nng_socket s, void *data, size_t *sizep, int flags);
+int nng_recvmsg(nng_socket s, nng_msg **msgp, int flags);
+void nng_recv_aio(nng_socket s, nng_aio *aio);
+
+These functions (nng_recv, nng_recvmsg, and nng_recv_aio) receive
+messages over the socket s. The differences in their behaviors are as follows.
+ + note +
+The semantics of what receving a message means varies from protocol to +protocol, so examination of the protocol documentation is encouraged. +Additionally, some protocols may not support receiving at all or may require other pre-conditions first. +(For example, REQ sockets cannot normally receive data until they have first sent a request, +while PUB sockets can only send data and never receive it.)
+The nng_recv function is the simplest to use, but is the least efficient.
+It receives the content in data, as a message size (in bytes) of up to the value stored in sizep,
+unless the NNG_FLAG_ALLOC flag is set in flags (see below.)
Upon success, the size of the message received will be stored in sizep.
+The flags is a bit mask made up of zero or more of the following values:
+NNG_FLAG_NONBLOCK:
+If the socket has no messages pending for reception at this time, it does not block, but returns immediately
+with a status of NNG_EAGAIN. If this flag is absent, the function will wait until data can be received.
NNG_FLAG_ALLOC:
+Instead of receiving the message into data, a new buffer will be allocated exactly large enough to hold
+the message. A pointer to that buffer will be stored at the location specified by data. This provides a form
+of zero-copy operation. The caller should dispose of the buffer using nng_free or by sending using
+nng_send with the NNG_FLAG_ALLOC flag.
+ + important +
+When using NNG_FLAG_ALLOC, it is important that the value of size match the actual allocated size of the data.
+Using an incorrect size results in unspecified behavior, which may include heap corruption, program crashes,
+or other undesirable effects.
The nng_recvmsg function receives a message and stores a pointer to the nng_msg for that message in msgp.
The flags can contain the value NNG_FLAG_NONBLOCK, indicating that the function should not wait if the socket
+has no messages available to receive. In such a case, it will return NNG_EAGAIN.
+ + tip +
+This function is preferred over nng_recv, as it gives access to the message structure and eliminates both
+a data copy and allocation, even when nng_recv is using NNG_FLAG_ALLOC.
The nng_send_aio function receives a message asynchronously, using the nng_aio aio, over the socket s.
+On success, the received message can be retrieved from the aio using the nng_aio_get_msg function.
+ + note +
+It is important that the application retrieves the message, and disposes of it accordingly. +Failure to do so will leak the memory.
++ + tip +
+This is the preferred function to use for receiving data on a socket. While it does require a few extra
+steps on the part of the application, the lowest latencies and highest performance will be achieved by using
+this function instead of nng_recv or nng_recvmsg.
int nng_socket_get_recv_poll_fd(nng_socket s, int *fdp);
int nng_socket_get_send_poll_fd(nng_socket s, int *fdp);
Sometimes it is necessary to integrate a socket into a poll or select driven
-event loop. (Or, on Linux, epoll, or on BSD derived systems like macOS kqueue).
epoll, or on BSD derived systems like macOS kqueue).
For these occasions, a suitable file descriptor for polling is provided by these two functions.
-The nng_socket_get_recv_poll_fd function obtains a file descriptor
+
The nng_socket_get_recv_poll_fd function obtains a file descriptor
that will poll as readable when a message is ready for receiving for the socket.
The nng_socket_get_send_poll_fd function obtains a file descriptor
+
The nng_socket_get_send_poll_fd function obtains a file descriptor
that will poll as readable when the socket can accept a message for sending.
These file descriptors should only be polled for readability, and no other operation performed on them. The socket will read from, or write to, @@ -498,6 +577,7 @@ when possible.
build a service that publishes a timestamp at one second intervals. Error handling is elided for the sake of clarity.#include <stdlib.h>
+#include <stdio.h>
#include <nng/nng.h>
#include <nng/protocol/pubsub0/pub.h>
@@ -514,7 +594,7 @@ void callback(void *arg) {
nng_time now;
struct state *state = arg;
if (nng_aio_result(state->aio) != 0) {
- nng_log_err("Error %s occurred", nng_strerror(nng_aio_result(state->aio)));
+ fprintf(stderr, "Error %s occurred", nng_strerror(nng_aio_result(state->aio)));
return; // terminate the callback loop
}
if (state->sleeping) {
@@ -543,6 +623,52 @@ int main(int argc, char **argv) {
}
}
+This example demonstrates the use of nng_aio, [nng_recv_aio], to build a client to
+watch for messages received from the service created in Example 2.
+Error handling is elided for the sake of clarity.
#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>>
+#include <nng/nng.h>
+#include <nng/protocol/pubsub0/sub.h>
+
+struct state {
+ nng_socket s;
+ nng_aio *aio;
+};
+
+static struct state state;
+
+void callback(void *arg) {
+ nng_msg *msg;
+ nng_time now;
+ struct state *state = arg;
+ if (nng_aio_result(state->aio) != 0) {
+ fprintf(stderr, "Error %s occurred", nng_strerror(nng_aio_result(state->aio)));
+ return; // terminate the callback loop
+ }
+ msg = nng_aio_get_msg(state->aio);
+ memcpy(&now, nng_msg_body(msg), sizeof (now)); // should check the length!
+ printf("Timestamp is %lu\n", (unsigned long)now);
+ nng_msg_free(msg);
+ nng_aio_set_msg(state->aio, NULL);
+ nng_recv_aio(state->s, state->aio);
+}
+
+int main(int argc, char **argv) {
+ const char *url = argv[1]; // should check this
+
+ nng_aio_alloc(&state.aio, NULL, NULL);
+ nng_sub0_open(&state.s);
+ nng_sub0_socket_subscribe(state.s, NULL, 0); // subscribe to everything
+ nng_dial(state.s, url, NULL, 0);
+ nng_recv_aio(state.s, state.aio); // kick it off right away
+ for(;;) {
+ nng_msleep(0x7FFFFFFF); // infinite, could use pause or sigsuspend
+ }
+}
+
--
cgit v1.2.3-70-g09d2