Provided by: libnng-dev_1.9.0-1_amd64 bug

NAME

       nng_ctx - protocol context

SYNOPSIS

           #include <nng/nng.h>

           typedef struct nng_ctx_s nng_ctx

DESCRIPTION

       An nng_ctx is a handle to an underlying context object, which keeps the protocol state for
       some stateful protocols. The purpose of a separate context object is to permit
       applications to share a single socket, with its various underlying dialers, listeners, and
       pipes, while still benefiting from separate state tracking.

       For example, a req context will contain the request ID of any sent request, a timer to
       retry the request on failure, and so forth. A separate context on the same socket can have
       similar data, but corresponding to a completely different request.

           Important
           The nng_ctx structure is always passed by value (both for input parameters and return
           values), and should be treated opaquely. Passing structures this way gives the
           compiler a chance to perform accurate type checks in functions passing values of this
           type.

       All contexts share the same socket, and so some options, as well as the underlying
       transport details, will be common to all contexts on that socket.

           Note
           Not every protocol supports separate contexts. See the protocol-specific documentation
           for further details about whether contexts are supported, and details about what
           options are supported for contexts.

       Protocols that make use of contexts will also have a default context that is used when the
       socket global operations are used. Operations using the global context will generally not
       interfere with any other contexts, except that certain socket options may affect socket
       global behavior.

       Historically, applications wanting to use a stateful protocol concurrently would have to
       resort to raw mode sockets, which bypasses much of the various protocol handling, leaving
       it to up to the application to do so. Contexts make it possible to still benefit from
       advanced protocol handling, including timeouts, retries, and matching requests to
       responses, while doing so concurrently.

           Note
           Raw mode sockets do not support contexts, since there is generally no state tracked
           for them, and thus contexts make no sense.

           Tip
           Contexts are an excellent mechanism to use when building concurrent applications, and
           should be used in lieu of raw mode sockets when possible.

           Important
           Use of file descriptor polling (with descriptors obtained using the NNG_OPT_RECVFD or
           NNG_OPT_SENDFD options) while contexts are in use on the same socket is not supported,
           and may lead to unpredictable behavior. These asynchronous methods should not be mixed
           on the same socket.

   Initialization
       A context may be initialized using the macro NNG_CTX_INITIALIZER before it is opened, to
       prevent confusion with valid open contexts.

EXAMPLE

       The following program fragment demonstrates the use of contexts to implement a concurrent
       rep service that simply echos messages back to the sender.

           struct echo_context {
               nng_ctx ctx;
               nng_aio *aio;
               enum { INIT, RECV, SEND } state;
           };

           void
           echo(void *arg)
           {
               struct echo_context *ec = arg;

               switch (ec->state) {
               case INIT:
                   ec->state = RECV;
                   nng_ctx_recv(ec->ctx, ec->aio);
                   return;
               case RECV:
                   if (nng_aio_result(ec->aio) != 0) {
                       // ... handle error
                   }
                   // We reuse the message on the ec->aio
                   ec->state = SEND;
                   nng_ctx_send(ec->ctx, ec->aio);
                   return;
               case SEND:
                   if (nng_aio_result(ec->aio) != 0) {
                       // ... handle error
                   }
                   ec->state = RECV;
                   nng_ctx_recv(ec->ctx, ec->aio);
                   return;
               }
           }

       Given the above fragment, the following example shows setting up the service. It assumes
       that the socket has already been created and any transports set up as well with functions
       such as nng_dial() or nng_listen().

           #define CONCURRENCY 1024

           static struct echo_context ecs[CONCURRENCY];

           void
           start_echo_service(nng_socket rep_socket)
           {
               for (int i = 0; i < CONCURRENCY; i++) {
                   // error checks elided for clarity
                   nng_ctx_open(&ecs[i].ctx, rep_socket);
                   nng_aio_alloc(&ecs[i].aio, echo, ecs+i);
                   ecs[i].state = INIT;
                   echo(ecs+i); // start it running
               }
           }

SEE ALSO

       libnng(3), nng_ctx_close(3), nng_ctx_open(3), nng_ctx_get(3), nng_ctx_id(3),
       nng_ctx_recv(3), nng_ctx_recvmsg(3), nng_ctx_send(3), nng_ctx_sendmsg(3), nng_ctx_set(3),
       nng_dialer(5), nng_listener(5), nng_socket(5), nng_options(5), nng(7)

                                            2024-10-11                                 NNG_CTX(5)