From fd6c89459e0f72c94c117c5a6084b4bdc539faaf Mon Sep 17 00:00:00 2001 From: gdamore Date: Wed, 1 Jan 2025 02:09:29 +0000 Subject: deploy: f0a65566a0879015cf75323ef4c3495e5ce3867e --- ref/api/sock.html | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 130 insertions(+), 4 deletions(-) (limited to 'ref/api/sock.html') diff --git a/ref/api/sock.html b/ref/api/sock.html index 6e8d92ef..5ac982b7 100644 --- a/ref/api/sock.html +++ b/ref/api/sock.html @@ -446,17 +446,96 @@ For example, the message may be sitting in queue, or located in TCP buffers, or steps on the part of the application, the lowest latencies and highest performance will be achieved by using this function instead of nng_send or nng_sendmsg.

+

Receiving Messages

+
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.)

+
+

nng_recv

+

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:

+ +
+

+ + 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.

+
+

nng_recvmsg

+

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.

+
+

nng_recv_aio

+

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.

+

Polling Socket Events

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).

+event loop. (Or, on Linux, 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) {
     }
 }
 
+

Example 3: Watching a Periodic Timestamp

+

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