Overview
RAW mode
Most applications will use sockets in normal, or cooked, mode. This mode provides the full semantics of the protocol. For example, REQ sockets will automatically match a reply to a request, and resend requests periodically if no reply was received.
There are situations, such as with proxies, where it is desirable to bypass these semantics and simply pass messages to and from the socket with no extra semantic handling. This is possible using raw mode sockets.
Raw mode sockets are generally constructed with a different function,
such as nng_req0_open_raw().
Using these sockets, the application can simply send and receive messages,
and is responsible for supplying any additional socket semantics.
Typically this means that the application will need to inspect message
headers on incoming messages, and supply them on outgoing messages.
tip
The nng_device() function only works with raw mode
sockets, but as it only forwards the messages, no additional application
processing is needed.
Protocols
The Scalability Protocols are a principally a collection of common networking patterns found in applications.
The following patterns are included:
Request/Reply
The request/reply pattern is made up of the REQ and REP protocols. This most often used when implementing RPC-like services, where a given request is matched by a single reply.
Pipeline
The pipeline pattern is made up of the PUSH and PULL protocols.
In this pattern communication is half-duplex, in that one side sends data and another side receives.
This pattern is also characterized by its ability to solve distribution problems, and the fact that it has back-pressure, providing a measure of flow control to data production and consumption.
BUS Protocol
The BUS protocol provides for building mesh networks where every peer is connected to every other peer. In this protocol, each message sent by a node is sent to every one of its directly connected peers.
tip
Messages are only sent to directly connected peers. This means that in the event that a peer is connected indirectly, it will not receive messages. When using this protocol to build mesh networks, it is therefore important that a fully-connected mesh network be constructed.
All message delivery in this pattern is best-effort, which means that peers may not receive messages. Furthermore, delivery may occur to some, all, or none of the directly connected peers. (Messages are not delivered when peer nodes are unable to receive.) Hence, send operations will never block; instead if the message cannot be delivered for any reason it is discarded.
tip
In order to minimize the likelihood of message loss, this protocol should not be used for high throughput communications. Furthermore, the more traffic in aggregate that occurs across the topology, the more likely that message loss is to occur.
Socket Operations
The nng_bus0_open() functions create a bus socket.
This socket may be used to send and receive messages.
Sending messages will attempt to deliver to each directly connected peer.
Protocol Versions
Only version 0 of this protocol is supported. (At the time of writing, no other versions of this protocol have been defined.)
Protocol Options
The BUS protocol has no protocol-specific options.
Protocol Headers
When using a BUS socket in raw mode, received messages will contain the incoming pipe ID as the sole element in the header. If a message containing such a header is sent using a raw BUS socket, then, the message will be delivered to all connected pipes except the one identified in the header. This behavior is intended for use with device configurations consisting of just a single socket. Such configurations are useful in the creation of rebroadcasters, and this capability prevents a message from being routed back to its source. If no header is present, then a message is sent to all connected pipes.
When using normal (cooked mode) BUS sockets, no message headers are present.
PAIR protocol
The PAIR protocol implements a peer-to-peer pattern, where relationships between peers are one-to-one.
Socket Operations
The nng_pair_open() functions create a PAIR socket.
Normally, this pattern will block when attempting to send a message if no peer is able to receive the message.
note
Even though this mode may appear to be reliable, because back-pressure prevents discarding messages most of the time, there are topologies involving where messages may be discarded. Applications that require reliable delivery semantics should consider using REQ sockets, or implement their own acknowledgment layer on top of PAIR sockets.
Protocol Versions
Version 0 is the legacy version of this protocol. It lacks any header information, and is suitable when building simple one-to-one topologies.
tip
Use version 0 if you need to communicate with other implementations, including the legacy libnanomsg library or mangos.
Version 1 of the protocol offers improved protection against loops when used with devices.
Polyamorous Mode
note
Polyamorous mode is deprecated, and support for it will likely be removed in a future release, when a suitable mesh protocol is available. In the meantime, applications are encouraged to look to other patterns.
Normally pair sockets are for one-to-one communication, and a given peer will reject new connections if it already has an active connection to another peer.
Polyamorous changes this, to allow a socket to communicate with
multiple directly-connected peers.
This mode is enabled by opening a socket using
nng_pair1_open_poly().
tip
Polyamorous mode is only available when using pair version 1.
In polyamorous mode a socket can support many one-to-one connections.
In this mode, the application must
choose the remote peer to receive an outgoing message by setting the
nng_pipe to use for the outgoing message using
nng_msg_set_pipe().
If no remote peer is specified by the sender, then the protocol will select any available connected peer.
Most often the value of the outgoing pipe will be obtained from an incoming
message using nng_msg_get_pipe(),
such as when replying to an incoming message.
note
Directed send only works with directly connected peers. It will not function across device proxies.
In order to prevent head-of-line blocking, if the peer on the given pipe is not able to receive (or the pipe is no longer available, such as if the peer has disconnected), then the message will be discarded with no notification to the sender.
Protocol Options
The following protocol-specific options are available.
-
NNG_OPT_MAXTTL: (int, version 1 only). Maximum time-to-live. -
NNG_OPT_PAIR1_POLY: (bool, version 1 only) This option is no longer supported. Formerly it was used to configure polyamorous mode, but that mode is now established by using thenng_pair1_open_poly()function.
Protocol Headers
Version 0 of the pair protocol has no protocol-specific headers.
Version 1 of the pair protocol uses a single 32-bit unsigned value. The
low-order (big-endian) byte of this value contains a “hop” count, and is
used in conjunction with the
NNG_OPT_MAXTTL option to guard against
device forwarding loops.
This value is initialized to 1, and incremented each time the message is
received by a new node.
PUB Protocol
The PUB protocol is one half of a publisher/subscriber pattern. In this pattern, a publisher sends data, which is broadcast to all subscribers. The subscribing applications only see the data to which they have subscribed.
The PUB protocol is the publisher side, and the SUB protocol is the subscriber side.
note
In this implementation, the publisher delivers all messages to all subscribers. The subscribers maintain their own subscriptions, and filter them locally. Thus, this pattern should not be used in an attempt to reduce bandwidth consumption.
The topics that subscribers subscribe to is just the first part of the message body. Applications should construct their messages accordingly.
Socket Operations
The [nng_pub0_open()][nng_pub_open] functions create a publisher socket.
This socket may be used to send messages, but is unable to receive them.
Attempts to receive messages will result in NNG_ENOTSUP.
Protocol Versions
Only version 0 of this protocol is supported. (At the time of writing, no other versions of this protocol have been defined.)
Protocol Options
The PUB protocol has no protocol-specific options.
Protocol Headers
The PUB protocol has no protocol-specific headers.
PULL protocol
The PULL protocol is one half of a pipeline pattern. The other half is the PUSH protocol.
In the pipeline pattern, pushers distribute messages to pullers. Each message sent by a pusher will be sent to one of its peer pullers, chosen in a round-robin fashion from the set of connected peers available for receiving. This property makes this pattern useful in load-balancing scenarios.
Socket Operations
The nng_pull0_open() functions create a
PULL socket.
This socket may be used to receive messages, but is unable to send them.
Attempts to send messages will result in NNG_ENOTSUP.
When receiving messages, the PULL protocol accepts messages as they arrive from peers. If two peers both have a message ready, the order in which messages are handled is undefined.
Protocol Versions
Only version 0 of this protocol is supported. (At the time of writing, no other versions of this protocol have been defined.)
Protocol Options
The PULL protocol has no protocol-specific options.
Protocol Headers
The PULL protocol has no protocol-specific headers.
PUSH protocol
DESCRIPTION
The PUSH protocol is one half of a pipeline pattern. The other side is the PULL protocol.
In the pipeline pattern, pushers distribute messages to pullers. Each message sent by a pusher will be sent to one of its peer pullers, chosen in a round-robin fashion from the set of connected peers available for receiving. This property makes this pattern useful in load-balancing scenarios.
Socket Operations
The nng_push0_open() call creates a PUSH socket.
This socket may be used to send messages, but is unable to receive them.
Attempts to receive messages will result in NNG_ENOTSUP.
Send operations will observe flow control (back-pressure), so that only peers capable of accepting a message will be considered. If no peer is available to receive a message, then the send operation will wait until one is available, or the operation times out.
note
Although the pipeline protocol honors flow control, and attempts to avoid dropping messages, no guarantee of delivery is made. Furthermore, as there is no capability for message acknowledgment, applications that need reliable delivery are encouraged to consider the REQ protocol instead.
Protocol Versions
Only version 0 of this protocol is supported. (At the time of writing, no other versions of this protocol have been defined.)
Protocol Options
NNG_OPT_SENDBUF: (int, 0 - 8192) Normally this is set to zero, indicating that send operations are unbuffered. In unbuffered operation, send operations will wait until a suitable peer is available to receive the message. If this is set to a positive value (up to 8192), then an intermediate buffer is provided for the socket with the specified depth (in messages).
note
Transport layer buffering may occur in addition to any socket buffer determined by this option.
Protocol Headers
The PUSH protocol has no protocol-specific headers.
REP Protocol
The REP protocol is one half of a request/reply pattern. In this pattern, a requester sends a message to one replier, who is expected to reply. The request is resent if no reply arrives, until a reply is received or the request times out.
tip
This protocol is useful in setting up RPC-like services. It is also reliable, in that a requester will keep retrying until a reply is received.
The REP protocol is the replier side, and the REP protocol is the requester side.
Socket Operations
The nng_rep0_open() functions create a replier socket.
This socket may be used to receive messages (requests), and then to send
replies.
Generally a reply can only be sent after receiving a request.
Send operations will result in NNG_ESTATE if no corresponding request
was previously received.
Likewise, only one receive operation may be pending at a time.
Any additional concurrent receive operations will result in NNG_ESTATE.
Raw mode sockets ignore all these restrictions.
Context Operations
This protocol supports the creation of contexts for concurrent use cases using nng_ctx_open().
Each context may have at most one outstanding request, and operates independently of the others. The restrictions for order of operations with sockets apply equally well for contexts, except that each context will be treated as if it were a separate socket.
Protocol Versions
Only version 0 of this protocol is supported. (At the time of writing, no other versions of this protocol have been defined.)
Protocol Options
The REP protocol has no protocol-specific options.
Protocol Headers
The REP protocol uses a backtrace in the header. This is more fully documented in the REQ chapter.
REQ protocol
The REQ protocol is one half of a request/reply pattern. In this pattern, a requester sends a message to one replier, who is expected to reply. The request is resent if no reply arrives, until a reply is received or the request times out.
tip
This protocol is useful in setting up RPC-like services. It is also “reliable”, in that a the requester will keep retrying until a reply is received.
note
Because requests are resent, it is important that they be idempotent to ensure predictable and repeatable behavior even in the face of duplicated requests, which can occur (for example if a reply message is lost for some reason.)
The requester generally only has one outstanding request at a time unless in raw mode, and it will generally attempt to spread work requests to different peer repliers.
tip
This property, when combined with a device can help provide a degree of load-balancing.
The REQ protocol is the requester side, and the REP protocol is the replier side.
Socket Operations
The nng_req0_open() functions create a REQ socket.
This socket may be used to send messages (requests), and then to receive replies.
Generally a reply can only be received after sending a request.
(Attempts to receive a message will result in NNG_ESTATE if there is no
outstanding request.)
Furthermore, only a single receive operation may be pending at a time.
Attempts to post more receive operations concurrently will result in
NNG_ESTATE.
Requests may be canceled by sending a different request. This will cause the requester to discard any reply from the earlier request, but it will not stop a replier from processing a request it has already received or terminate a request that has already been placed on the wire.
Raw mode sockets ignore all these restrictions.
Context Operations
This protocol supports the creation of contexts for concurrent
use cases using nng_ctx_open().
The NNG_OPT_REQ_RESENDTIME value may be configured differently
on contexts created this way.
Each context may have at most one outstanding request, and operates independently from the others.
The restrictions for order of operations with sockets apply equally well for contexts, except that each context will be treated as if it were a separate socket.
Protocol Versions
Only version 0 of this protocol is supported. (At the time of writing, no other versions of this protocol have been defined.)
Protocol Options
The following protocol-specific option is available.
-
NNG_OPT_REQ_RESENDTIME:
(nng_duration)
When a new request is started, a timer of this duration is also started. If no reply is received before this timer expires, then the request will be resent.
Requests are also automatically resent if the peer to whom the original request was sent disconnects.
Resending may be deferred up to the value of theNNG_OPT_RESENDTICKparameter.
If the value is set toNNG_DURATION_INFINITE, then resends are disabled altogether. This should be used when the request is not idemptoent. -
NNG_OPT_REQ_RESENDTICK:
(nng_duration)
This is the granularity of the clock that is used to check for resending. The default is a second. Setting this to a higher rate will allow for more timely resending to occur, but may incur significant additional overhead when the socket has many outstanding requests (contexts).
When there are no requests outstanding that have a resend set, then the clock does not tick at all.
This option is shared for all contexts on a socket, and is only available for the socket itself.
Protocol Headers
This protocol uses a backtrace in the header. This form uses a stack of 32-bit big-endian identifiers. There must be at least one identifier, the request ID, which will be the last element in the array, and must have the most significant bit set.
There may be additional peer IDs preceding the request ID. These will be distinguishable from the request ID by having their most significant bit clear.
When a request message is received by a forwarding node (such as a device), the forwarding node prepends a 32-bit peer ID (which must have the most significant bit clear), which is the forwarder’s way of identifying the directly connected peer from which it received the message. (This peer ID, except for the most significant bit, has meaning only to the forwarding node itself.)
It may help to think of prepending a peer ID as pushing a peer ID onto the front of the stack of headers for the message. (It will use the peer ID it popped from the front to determine the next intermediate destination for the reply.)
When a reply message is created, it is created using the same headers that the request contained.
A forwarding node can pop the peer ID it originally pushed on the message, stripping it from the front of the message as it does so.
When the reply finally arrives back at the initiating requester, it should have only a single element in the message, which will be the request ID it originally used for the request.
RESPONDENT protocol
The RESPONDENT protocol is one half of a survey pattern. In this pattern, a surveyor sends a survey, which is broadcast to all peer respondents. The respondents then have a chance to reply (but are not obliged to reply). The survey itself is a timed event, so that responses received after the survey has finished are discarded.
tip
This protocol is useful in solving voting problems, such as leader election in cluster configurations, as well as certain kinds of service discovery problems.
The RESPONDENT protocol is the respondent side, and the SURVEYOR protocol is the surveyor side.
Socket Operations
The nng_respondent0_open() functions create a
respondent socket.
This socket may be used to receive messages, and then to send replies.
A reply can only be sent after receiving a survey, and generally the
reply will be sent to surveyor from whom the last survey was received.
Respondents may discard a survey by simply not replying to it.
Raw mode sockets ignore all these restrictions.
Context Operations
This protocol supports the creation of contexts for concurrent
use cases using nng_ctx_open().
Incoming surveys will be routed to and received by only one context. Additional surveys may be received by other contexts in parallel. Replies made using a context will be returned to the the surveyor that issued the survey most recently received by that context. The restrictions for order of operations with sockets apply equally well for contexts, except that each context will be treated as if it were a separate socket.
Protocol Versions
Only version 0 of this protocol is supported. At the time of writing, no other versions of this protocol have been defined. 1
An earlier and incompatible version of the protocol was used in older pre-releases of nanomsg, but was not released in any production version.
Protocol Options
The respondent protocol has no protocol-specific options.
Protocol Headers
The RESPONDENT protocol uses a backtrace in the header. This is more fully documented in the SURVEYOR manual.
SUB protocol
The SUB protocol is one half of a publisher/subscriber pattern. In this pattern, a publisher sends data, which is broadcast to all subscribers. The subscribing applications only see the data to which they have subscribed.
The SUB protocol is the subscriber side, and the PUB protocol is the publisher side.
note
The publisher delivers all messages to all subscribers. The subscribers maintain their own subscriptions, and filter them locally. Thus, this pattern should not be used in an attempt to reduce bandwidth consumption.
The topics that subscribers subscribe to is compared to the leading bytes of the message body. Applications should construct their messages accordingly.
Socket Operations
The nng_sub0_open() functions create a SUB socket.
This socket may be used to receive messages, but is unable to send them.
Attempts to send messages will result in NNG_ENOTSUP.
Protocol Versions
Only version 0 of this protocol is supported. (At the time of writing, no other versions of this protocol have been defined.)
Protocol Options
The following protocol-specific options are available.
-
NNG_OPT_SUB_SUBSCRIBE:
This option registers a topic that the subscriber is interested in. The option is write-only, and takes an array of bytes, of arbitrary size. Each incoming message is checked against the list of subscribed topics. If the body begins with the entire set of bytes in the topic, then the message is accepted. If no topic matches, then the message is discarded.
This option is a byte array. Thus if you usenng_socket_set_string()theNULterminator byte will be included in the topic. If that isn’t desired, consider usingnng_socket_set()and usingstrlen()of the topic as the topic size.
To receive all messages, an empty topic (zero length) can be used. -
NNG_OPT_SUB_UNSUBSCRIBE:
This option, also read-only, removes a topic from the subscription list. Note that if the topic was not previously subscribed to withNNG_OPT_SUB_SUBSCRIBEthen anNNG_ENOENTerror will result. -
NNG_OPT_SUB_PREFNEW:
(bool)
This read/write option specifies the behavior of the subscriber when the queue is full. Whentrue(the default), the subscriber will make room in the queue by removing the oldest message. Whenfalse, the subscriber will reject messages if the message queue does not have room.
Protocol Headers
The SUB protocol has no protocol-specific headers.
SURVEYOR protocol
The SURVEYOR protocol is one half of a survey pattern. In this pattern, a surveyor sends a survey, which is broadcast to all peer respondents. The respondents then have a chance, but are not obliged, to reply. The survey itself is a timed event, so that responses received after the survey has finished are discarded.
tip
This protocol is useful in solving voting problems, such as leader election in cluster configurations, as well as certain kinds of service discovery problems.
The SURVEYOR protocol is the surveyor side, and the RESPONDENT protocol is the respondent side.
Socket Operations
The nng_surveyor0_open()
functions create a surveyor socket.
This socket may be used to send messages (surveys), and then to receive replies.
A reply can only be received after sending a survey.
A surveyor can normally expect to receive at most one reply from each responder.
(Messages can be duplicated in some topologies,
so there is no guarantee of this.)
Attempts to receive on a socket with no outstanding survey will result
in NNG_ESTATE.
If the survey times out while the surveyor is waiting
for replies, then the result will be NNG_ETIMEDOUT.
Only one survey can be outstanding at a time; sending another survey will cancel the prior one, and any responses from respondents from the prior survey that arrive after this will be discarded.
Raw mode sockets ignore all these restrictions.
Context Operations
This protocol supports the creation of contexts for concurrent
use cases using nng_ctx_open().
Each context can initiate its own surveys, and it will receive only responses to its own outstanding surveys. Other contexts on the same socket may have overlapping surveys operating at the same time.
Each of these may have their own timeouts established with
NNG_OPT_SURVEYOR_SURVEYTIME.
Additionally, sending a survey on a context will only cancel an outstanding survey on the same context.
note
Due to the best-effort nature of this protocol, if too may contexts are attempting to perform surveys simultaneously, it is possible for either individual outgoing surveys or incoming responses to be lost.
Protocol Versions
Only version 0 of this protocol is supported. At the time of writing, no other versions of this protocol have been defined. 1
An earlier and incompatible version of the protocol was used in older pre-releases of nanomsg, but was not released in any production version.
Protocol Options
The following protocol-specific option is available.
NNG_OPT_SURVEYOR_SURVEYTIME:
(nng_duration)
When a new survey is started, a timer of this duration is started. Any responses arriving this time will be discarded. Attempts to receive after the timer expires with no other surveys started will result inNNG_ESTATE.
If a receive is pending when this timer expires, it will result inNNG_ETIMEDOUT.
Protocol Headers
This form uses a stack of 32-bit big-endian identifiers. There must be at least one identifier, the survey ID, which will be the last element in the array, and must have the most significant bit set.
There may be additional peer IDs preceding the survey ID. These will be distinguishable from the survey ID by having their most significant bit clear.
When a survey message is received by a forwarding node (such as a device), the forwarding node prepends a 32-bit peer ID (which must have the most significant bit clear), which is the forwarder’s way of identifying the directly connected peer from which it received the message. (This peer ID, except for the most significant bit, has meaning only to the forwarding node itself.)
It may help to think of prepending a peer ID as pushing a peer ID onto the front of the stack of headers for the message. (It will use the peer ID it popped from the front to determine the next intermediate destination for the response.)
When a response message is created, it is created using the same headers that the survey contained.
A forwarding node can pop the peer ID it originally pushed on the message, stripping it from the front of the message as it does so.
When the response finally arrives back at the initiating surveyor, it should have only a single element in the message, which will be the survey ID it originally used for the request.
More detail can be found in the sp-surveyor-01 RFC document.
Transports
This chapter provides information about the various transports that NNG supports. Transports may be thought of as different underlying communications technologies, such as TCP, Websockets, and so forth.
INPROC
The inproc transport provides intra-process communication within a single process.
TCP
The tcp transport provides communication over TCP/IP networks.
IPC Transport
DESCRIPTION
The ipc transport provides communication support between sockets within different processes on the same host. For POSIX platforms, this is implemented using UNIX domain sockets. For Windows, this is implemented using Windows named pipes. Other platforms may have different implementation strategies.
URI Formats
Traditional Names
This transport uses URIs using the scheme ipc://, followed by a path
name in the file system where the socket or named pipe should be created.
tip
On Windows, all names are prefixed by \\.\pipe\ and do not
reside in the normal file system.
On POSIX platforms, the path is taken literally, and is relative to
the current directory, unless it begins with /, in which case it is
relative to the root directory.
note
When using relative paths on POSIX systems, the address used and returned
in properties like NNG_OPT_LOCADDR and NNG_OPT_URL will also be relative.
Consequently, they will only be interpreted the same by processes that have
the same working directory.
To ensure maximum portability and safety, absolute paths are recommended
whenever possible.
note
If compatibility with legacy nanomsg applications is required,
then path names must not be longer than 122 bytes, including the final
NUL byte.
This is because legacy versions of nanomsg cannot express URLs
longer than 128 bytes, including the ipc:// prefix.
UNIX Aliases
The unix:// scheme is an alias for ipc:// and can be used inter-changeably, but only on POSIX systems.1
The purpose of this scheme is to support a future transport making use of AF_UNIX
on Windows systems, at which time it will be necessary to discriminate between
the Named Pipes and the AF_UNIX based transports.
Abstract Names
On Linux, this transport also can support abstract sockets.
Abstract sockets use a URI-encoded name after the abstract:// scheme, which allows arbitrary values to be conveyed
in the path, including embedded NUL bytes.
For example, the name "a\0b" would be represented as abstract://a%00b.
tip
An empty name may be used with a listener to request “auto bind” be used to select a name.
In this case the system will allocate a free name.
The name assigned may be retrieved using NNG_OPT_LOCADDR.
Abstract names do not include the leading NUL byte used in the low-level socket address.
Abstract sockets do not have any representation in the file system, and are automatically freed by the system when no longer in use.
Abstract sockets ignore socket permissions, but it is still possible to determine the credentials
of the peer with NNG_OPT_PEER_UID, and similar options.2
This property makes it important that names be chosen randomly to prevent unauthorized access, or that checks against the peer credentials are made, or ideally, both.
Socket Address
When using an nng_sockaddr structure,
the actual structure is of type nng_sockaddr_ipc,
except for abstract sockets, which use nng_sockaddr_abstract.
Transport Options
The following transport options are supported by this transport, where supported by the underlying platform.
NNG_OPT_IPC_PERMISSIONSNNG_OPT_IPC_SECURITY_DESCRIPTORNNG_OPT_LOCADDRNNG_OPT_REMADDRNNG_OPT_PEER_GIDNNG_OPT_PEER_PIDNNG_OPT_PEER_UIDNNG_OPT_PEER_ZONEIDNNG_OPT_URL
INPROC Transport
The inproc transport{{intra-process}} provides communication support between sockets within the same process. This may be used as an alternative to slower transports when data must be moved within the same process.
This transport tries hard to avoid copying data, and thus is very light-weight.
URI Format
This transport uses URIs using the scheme inproc://, followed by
an arbitrary string of text, terminated by a NUL byte.
Multiple URIs can be used within the same application, and they will not interfere with one another.
Two applications may also use the same URI without interfering with each other, and they will be unable to communicate with each other using that URI.
Socket Address
When using an nng_sockaddr structure,
the actual structure is of type
nng_sockaddr_inproc.
Transport Options
The inproc transport has no special options.
note
While inproc accepts the option [NNG_OPT_RECVMAXSZ] for
compatibility, the value of the option is ignored with no enforcement.
As inproc peers are in the same address space, they are implicitly
trusted, so the protection afforded by NNG_OPT_RECVMAXSZ is unnecessary.
Mixing Implementations
When mixing the NNG library with other implementations of these protocols in the same process (such as the mangos or libnanomsg implementations), it will not be possible to utilize the inproc transport to communicate across this boundary.
This limitation also extends to using different instances of the NNG library within the same process.
TCP transport
The tcp transport provides communication support between sockets across a TCP/IP network.
Both IPv4 and IPv6 are supported when the underlying platform also supports it.
URI Format
This transport uses URIs using the scheme tcp://, followed by
an IP address or hostname, followed by a colon and finally a
TCP port number.
For example, to contact port 80 on the localhost either of the following URIs
could be used: tcp://127.0.0.1:80 or tcp://localhost:80.
A URI may be restricted to IPv6 using the scheme tcp6://, and may
be restricted to IPv4 using the scheme tcp4://.
note
Specifying tcp6:// may not prevent IPv4 hosts from being used with
IPv4-in-IPv6 addresses, particularly when using a wildcard hostname with
listeners.
The details of this varies across operating systems.
note
Both tcp6:// and tcp4:// are specific to NNG, and might not
be understood by other implementations.
tip
We recommend using either numeric IP addresses, or names that are specific to either IPv4 or IPv6 to prevent confusion and surprises.
When specifying IPv6 addresses, the address must be enclosed in
square brackets ([]) to avoid confusion with the final colon
separating the port.
For example, the same port 80 on the IPv6 loopback address (::1) would
be specified as tcp://[::1]:80.
The special value of 0 (INADDR_ANY)
can be used for a listener to indicate that it should listen on all
interfaces on the host.
A short-hand for this form is to either omit the address, or specify
the asterisk (*) character.
For example, the following three URIs are all equivalent,
and could be used to listen to port 9999 on the host:
tcp://0.0.0.0:9999tcp://*:9999tcp://:9999
The entire URI must be less than NNG_MAXADDRLEN bytes long.
Socket Address
When using an nng_sockaddr structure,
the actual structure is either of type
nng_sockaddr_in (for IPv4) or
nng_sockaddr_in6 (for IPv6).
Transport Options
The following transport options are supported by this transport, where supported by the underlying platform.
BSD Socket Transport (Experimental)
The socket transport supports communication between
peers across arbitrary BSD sockets, such as those that are
created with nng_socket_pair().
This transport only supports listeners,
using [nng_listener_create()][nng_listener_create].
note
Attempts to create dialers using this transport will result in NNG_ENOTSUP.
The socket file descriptor is passed to the listener using
the NNG_OPT_SOCKET_FD option (as an integer).
Setting this option will cause the listener to create a pipe
backed by the file descriptor.
The protocol between peers using this transport is compatible with the protocol used for the tcp transport, but this is an implementation detail and subject to change without notice.1
Specifically it is not compatible with the ipc transport.
note
This transport is experimental, and at present is only supported on POSIX platforms.2
Windows lacks a suitable socketpair() equivalent function we could use.
Registration
No special action is necessary to register this transport.
URI Format
This transport uses the URL socket://, without further qualification.
Socket Address
The socket address will be of family NNG_AF_UNSPEC.
There are no further socket details available.
Transport Options
The following transport option is available:
NNG_OPT_SOCKET_FD:
(int)
This is a write-only option, that may be set multiple times on a listener. Each time this is set, the listener will create a pipe backed by the given file descriptor passed as an argument.
Additionally, the following options may be supported on pipes when the platform supports them:
API Reference
This chapter documents the functions and data structures that make up the NNG programming interface.
note
Interfaces not documented here are not considered public or stable, and they may be removed or altered in incompatible ways at any time.
We have organized the reference material along general functional areas. They are:
- Messages
- Sockets
- Contexts
- Options
- Dialers, Listeners, and Pipes
- Asynchronous I/O
- Asynchronous I/O for Providers
- Utility Functions
- Threads and Synchronization
- HTTP Client
- HTTP Server
- TLS Support
- Connected Streams
- Statistics
- Legacy Compatibility
Messages
Messages in Scalability Protocols are the fundamental unit of transmission and reception, as these protocols are fundamentally message-oriented.
Message object
An nng_msg represents a single message sent between Scalability Protocols peers.
Messages have a body, containing the application supplied payload, and a header, containing protocol specific routing and similar related information.
tip
Only applications using raw mode need to access the message header.
Creating, Destroying and Using
Messages are allocated using nng_msg_alloc(),
and are deallocated using nng_msg_free().
In addition there are other functions used to access message contents, including adding data to either the beginning or end of the message, automatic data conversion, and removing data from the beginning or end.
Performance Considerations
While there are convenience wrappers for sending and receiving arrays of bytes, using message objects directly when possible will give better performance by reducing data copies and needless allocations.
These functions are designed to try to avoid copying message contents by making use of scratch areas at the beginning and end of the message. These scratch areas, the “headroom” and “tailroom”, are automatically included when allocating a message.
Direct Use Forbidden
The nng_msg structure is opaque, and applications should never try to
rely on the size of it, nor access internal members directly.
This insulates the application from changes in subsequent NNG versions
that would affect the binary representation of the nng_msg itself.
Examples
Example 1: Preparing a message for use
#include <nng/nng.h>
nng_msg *m;
if (nng_msg_alloc(&m, strlen("content") + 1) != 0) {
// handle error
}
strcpy(nng_msg_body(m), "content");
Example 2: Preallocating message content
if (nng_msg_alloc(&m, 1024) != 0) {
// handle error
}
while ((val64 = next_datum()) != 0) P
if (nng_msg_append_u64(m, val64) != 0) {
// handle error
}
}
See Also
nng_aio_get_msg, nng_aio_set_msg, nng_msg_alloc, nng_msg_append, nng_msg_body, nng_msg_capacity, nng_msg_dup, nng_msg_free, nng_msg_header, nng_msg_header_append, nng_msg_header_chop, nng_msg_header_clear, nng_msg_header_insert, nng_msg_header_len, nng_msg_header_trim, nng_msg_insert, nng_msg_len, nng_msg_reserve, nng_msg_realloc, nng_msg_set_pipe, nng_msg_trim, nng_recvmsg, nng_sendmsg
nng_msg_alloc
NAME
nng_msg_alloc — allocate a message
SYNOPSIS
#include <nng/nng.h>
int nng_msg_alloc(nng_msg **msgp, size_t size);
DESCRIPTION
The nng_msg_alloc() function allocates a new message with body length size
and stores the result in msgp.
Messages allocated with this function contain a body and optionally a header.
They are used with receive and transmit functions.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient free memory exists to allocate a message.
SEE ALSO
nng_msg_free, nng_msg_body, nng_msg_dup, nng_msg_header, nng_msg_header_len, nng_msg_len, nng_msg_capacity, nng_msg_reserve, nng_msg_realloc
nng_msg_append
NAME
nng_msg_append — append to message body
SYNOPSIS
#include <nng/nng.h>
int nng_msg_append(nng_msg *msg, const void *val, size_t size);
int nng_msg_append_u16(nng_msg *msg, uint16_t val16);
int nng_msg_append_u32(nng_msg *msg, uint32_t val32);
int nng_msg_append_u64(nng_msg *msg, uint64_t val64);
DESCRIPTION
The nng_msg_append() family of functions appends data to
the end of the body of message msg, reallocating it if necessary.
The first function appends size bytes, copying them from val.
The remaining functions append the value specified (such as val32) in
network-byte order (big-endian).
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient free memory exists.
SEE ALSO
nng_msg_alloc, nng_msg_body, nng_msg_capacity, nng_msg_chop, nng_msg_clear, nng_msg_free, nng_msg_insert, [nng_msg_len][nng_msg_len.md], nng_msg_reserve, nng_msg_realloc, nng_msg_trim
nng_msg_body
NAME
nng_msg_body — return message body
SYNOPSIS
#include <nng/nng.h>
void *nng_msg_body(nng_msg *msg);
DESCRIPTION
The nng_msg_body() function returns a pointer to the start of the body
content of the message msg.
note
The value returned by this is invalidated by a call to any of the
functions that modify the message itself.
Such functions are
nng_msg_free(),
nng_msg_realloc(),
any of the nng_msg_trim(),
nng_msg_chop(),
nng_msg_append(),
or nng_msg_insert() variants.
RETURN VALUES
Pointer to start of message body.
SEE ALSO
nng_msg_alloc, nng_msg_append, nng_msg_capacity, nng_msg_chop, nng_msg_clear, nng_msg_free, nng_msg_insert, nng_msg_len, nng_msg_reserve, nng_msg_realloc, nng_msg_trim
nng_msg_capacity
NAME
nng_msg_capacity — return message body length
SYNOPSIS
#include <nng/nng.h>
size_t nng_msg_capacity(nng_msg *msg);
DESCRIPTION
The nng_msg_capacity() returns the storage allocated for the body of message msg.
The capacity includes the current contents of the message and free space after it.
The message body may grow to capacity without performing any further allocations.
RETURN VALUES
Allocated capacity for message body.
SEE ALSO
nng_msg_alloc, nng_msg_realloc, nng_msg_reserve nng_msg_body
nng_msg_chop
NAME
nng_msg_chop — remove data from end of message body
SYNOPSIS
#include <nng/nng.h>
int nng_msg_chop(nng_msg *msg, size_t size);
int nng_msg_chop_u16(nng_msg *msg, uint16_t *val16);
int nng_msg_chop_u32(nng_msg *msg, uint32_t *val32);
int nng_msg_chop_u64(nng_msg *msg, uint64_t *val64);
DESCRIPTION
The nng_msg_chop() family of functions removes data from
the end of the body of message msg.
The first function removes size bytes.
The remaining functions remove 2, 4, or 8 bytes, and stores them in the value
(such as val32),
after converting them from network-byte order (big-endian) to native byte order.
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_EINVAL: The message body is too short to remove the requested data.
SEE ALSO
nng_msg_alloc, nng_msg_append, nng_msg_body, nng_msg_capacity, nng_msg_clear, nng_msg_free, nng_msg_insert, nng_msg_len, nng_msg_reserve, nng_msg_realloc, nng_msg_trim
nng_msg_clear
NAME
nng_msg_clear — clear message body content
SYNOPSIS
#include <nng/nng.h>
void nng_msg_clear(nng_msg *msg);
DESCRIPTION
The nng_msg_clear() function resets the body length of message msg to zero.
SEE ALSO
nng_msg_alloc, nng_msg_capacity, nng_msg_reserve
nng_msg_dup
NAME
nng_msg_dup — duplicate a message
SYNOPSIS
#include <nng/nng.h>
int nng_msg_dup(nng_msg **dup, nng_msg_t *orig);
DESCRIPTION
The nng_msg_dup() makes a duplicate of the original message orig, and
saves the result in the location pointed by dup.
The actual message body and header content is copied,
but the duplicate may contain a
different amount of unused space than the original message.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient free memory exists to duplicate a message.
SEE ALSO
nng_msg_free
NAME
nng_msg_free — free a message
SYNOPSIS
#include <nng/nng.h>
void nng_msg_free(nng_msg *msg);
DESCRIPTION
The nng_msg_free() function deallocates the message msg entirely.
SEE ALSO
nng_msg_alloc, nng_msg_realloc
nng_msg_get_pipe
NAME
nng_msg_get_pipe — get pipe for message
SYNOPSIS
#include <nng/nng.h>
nng_pipe nng_msg_get_pipe(nng_msg *msg);
DESCRIPTION
The nng_msg_get_pipe() returns the nng_pipe object
associated with message msg.
On receive, this is the pipe from which a message was received.
On transmit, this would be the pipe that the message should be delivered
to, if a specific peer is required.
note
Not all protocols support overriding the destination pipe.
The most usual use case for this is to obtain information about the peer
from which the message was received.
This can be used to provide different behaviors for different peers, such as
a higher level of authentication for peers located on an untrusted network.
The [nng_pipe_get()][nng_pipe_get] function
is useful in this situation.
RETURN VALUES
This function returns the pipe associated with this message, which will be a positive value. If the pipe is non-positive, then that indicates that no specific pipe is associated with the message.
SEE ALSO
nng_msg_alloc, nng_msg_set_pipe, [nng_pipe_get][nng_pipe_get]
nng_msg_header
NAME
nng_msg_header — return message header
SYNOPSIS
#include <nng/nng.h>
void *nng_msg_header(nng_msg *msg);
DESCRIPTION
The nng_msg_header() function returns a pointer to the start of the header
content of the message msg.
note
The message header contains protocol-specific header content. Most applications should not need to access this content, but it is available for raw mode sockets.
note
The value returned by this is invalidated by a call to any of the functions that modify the message or the header content.
RETURN VALUES
Pointer to start of message header.
SEE ALSO
nng_msg_alloc, nng_msg_body, nng_msg_free, nng_msg_header_append, nng_msg_header_chop, nng_msg_header_insert nng_msg_header_len, nng_msg_header_trim
nng_msg_header_append
NAME
nng_msg_header_append — append to message header
SYNOPSIS
#include <nng/nng.h>
int nng_msg_header_append(nng_msg *msg, const void *val, size_t size);
int nng_msg_header_append_u16(nng_msg *msg, uint16_t val16);
int nng_msg_header_append_u32(nng_msg *msg, uint32_t val32);
int nng_msg_header_append_u64(nng_msg *msg, uint64_t val64);
DESCRIPTION
The nng_msg_header_append() family of functions appends data to
the end of the header of message msg, reallocating it if necessary.
The first function appends size bytes, copying them from val.
The remaining functions append the value (such as val32) in network-byte order (big-endian).
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient free memory exists.
SEE ALSO
nng_msg_header, nng_msg_header_chop, nng_msg_header_insert nng_msg_header_len, nng_msg_header_trim
nng_msg_header_chop
NAME
nng_msg_header_chop — remove data from end of message header
SYNOPSIS
#include <nng/nng.h>
int nng_msg_header_chop(nng_msg *msg, size_t size);
int nng_msg_header_chop_u16(nng_msg *msg, uint16_t *val16);
int nng_msg_header_chop_u32(nng_msg *msg, uint32_t *val32);
int nng_msg_header_chop_u64(nng_msg *msg, uint64_t *val64);
DESCRIPTION
The nng_msg_header_chop() family of functions removes
data from the end of the header of message msg.
The first function removes size bytes.
The remaining functions remove 2, 4, or 8 bytes, and stores them in the value
(such as val32),
after converting them from network-byte order (big-endian) to native
byte order.
RETURN VALUES
These function return 0 on success, and non-zero otherwise.
ERRORS
NNG_EINVAL: The message header is too short to remove the requested data.
SEE ALSO
nng_msg_header, nng_msg_header_append, nng_msg_header_insert nng_msg_header_len, nng_msg_header_trim
nng_msg_header_clear
NAME
nng_msg_header_clear — clear message header
SYNOPSIS
#include <nng/nng.h>
void nng_msg_header_clear(nng_msg *msg);
DESCRIPTION
The nng_msg_clear() function resets the header length of messaage msg to zero.
SEE ALSO
nng_msg_header, nng_msg_header_len
nng_msg_header_insert
NAME
nng_msg_header_insert — prepend to message header
SYNOPSIS
#include <nng/nng.h>
int nng_msg_header_insert(nng_msg *msg, const void *val, size_t size);
int nng_msg_header_insert_u16(nng_msg *msg, uint16_t val16);
int nng_msg_header_insert_u32(nng_msg *msg, uint32_t val32);
int nng_msg_header_insert_u64(nng_msg *msg, uint64_t val64);
DESCRIPTION
The nng_msg_header_insert() family of functions
prepends data to the front of the headers of message msg, reallocating
if necessary.
The first function prepends size bytes, copying them from val.
The remaining functions prepend the specified value (such as val32) in
network-byte order (big-endian).
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient free memory exists.
SEE ALSO
nng_msg_header, nng_msg_header_append nng_msg_header_chop, nng_msg_header_len, nng_msg_header_trim
nng_msg_header_len
NAME
nng_msg_header_len — return message header length
SYNOPSIS
#include <nng/nng.h>
size_t nng_msg_header_len(nng_msg *msg);
DESCRIPTION
The nng_msg_header_len() returns the length of the header of message msg.
RETURN VALUES
Length of message header.
SEE ALSO
nng_msg_header_trim
NAME
nng_msg_header_trim — remove data from start of message header
SYNOPSIS
#include <nng/nng.h>
int nng_msg_header_trim(nng_msg *msg, size_t size);
int nng_msg_header_trim_u16(nng_msg *msg, uint16_t *val16);
int nng_msg_header_trim_u32(nng_msg *msg, uint32_t *val32);
int nng_msg_header_trim_u64(nng_msg *msg, uint64_t *val64);
DESCRIPTION
The nng_msg_header_trim() family of functions remove
data from the start of the header of message msg.
The first function removes size bytes.
The remaining functions removes 2, 4, or 8 bytes, and stores them in the
value (such as val32),
after converting them from network-byte order (big-endian) to native
byte order.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_EINVAL: The message header is too short to remove the requested data.
SEE ALSO
nng_msg_header, nng_msg_header_append, nng_msg_header_chop nng_msg_header_insert nng_msg_header_len,
nng_msg_insert
NAME
nng_msg_insert — prepend to message body
SYNOPSIS
#include <nng/nng.h>
int nng_msg_insert(nng_msg *msg, const void *val, size_t size);
int nng_msg_insert_u16(nng_msg *msg, uint16_t val16);
int nng_msg_insert_u32(nng_msg *msg, uint32_t val32);
int nng_msg_insert_u64(nng_msg *msg, uint64_t val64);
DESCRIPTION
The nng_msg_insert() family of functions prepends data to
the front of the body of message msg, reallocating it if necessary.
The first function prepends size bytes, copying them from val.
The remaining functions prepend the specified value (such as val32)
in network-byte order (big-endian).
tip
These functions make use of space pre-allocated in front of the message body if available, so they can often avoid performing any reallocation. Applications should use these instead of reallocating and copying message content themselves, in order to benefit from this capability.
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient free memory exists.
SEE ALSO
nng_msg_alloc, nng_msg_append, nng_msg_body, nng_msg_capacity, nng_msg_chop, nng_msg_clear, nng_msg_free, nng_msg_insert, nng_msg_len, nng_msg_reserve, nng_msg_realloc, nng_msg_trim
nng_msg_len
NAME
nng_msg_len — return message body length
SYNOPSIS
#include <nng/nng.h>
size_t nng_msg_len(nng_msg *msg);
DESCRIPTION
The nng_msg_len() returns the length of the body of message msg.
RETURN VALUES
Length of message body.
SEE ALSO
nng_msg_realloc(3)
NAME
nng_msg_realloc — reallocate a message
SYNOPSIS
#include <nng/nng.h>
int nng_msg_realloc(nng_msg *msg, size_t size);
DESCRIPTION
The nng_msg_realloc() function re-allocates a [message][] so that it has
a body of length size.
This message attempts to avoid extra allocations,
and will reuse the existing memory when possible.
TIP: nng_msg_realloc is suitable for creating space for direct writing of data.
When appending many small pieces of data to a message using nng_msg_append(),
allocations may be reduced by first using
nng_msg_reserve()
to create sufficient space.
In any case, reallocating or appending to a message is guaranteed to succeed if the resulting
body length is less than nng_msg_capacity().
note
Pointers to message body and header content obtained prior to this function must not be in use, as the underlying memory used for the message may have changed, particularly if the message size is increasing.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient free memory exists to reallocate a message.
SEE ALSO
nng_msg_alloc, nng_msg_reserve, nng_msg_append, nng_msg_body, nng_msg_chop, nng_msg_free, nng_msg_insert, nng_msg_len, nng_msg_trim
nng_msg_reserve
NAME
nng_msg_reserve — reserve storage for a message
SYNOPSIS
#include <nng/nng.h>
int nng_msg_reserve(nng_msg *msg, size_t capacity);
DESCRIPTION
The nng_msg_reserve() function ensures a message has allocated enough storage
to accommodate a body of the given length.
This message attempts to avoid extra allocations,
and will reuse the existing memory when possible.
tip
Using this message before nng_msg_append()
will prevent additional memory allocations until the message’s length exceeds
the alotted capacity.
important
Pointers to message body and header content obtained prior to this function must not be in use, as the underlying memory used for the message may have changed, particularly if the message capacity is increasing.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient free memory exists to reallocate a message.
SEE ALSO
nng_msg_alloc, nng_msg_append, nng_msg_capacity, nng_msg_insert, nng_msg_len
nng_msg_set_pipe
NAME
nng_msg_set_pipe — set pipe for message
SYNOPSIS
#include <nng/nng.h>
void nng_msg_set_pipe(nng_msg *msg, nng_pipe p);
DESCRIPTION
The nng_msg_set_pipe() sets the pipe associated with message m to p.
This is most often useful when used with protocols that support directing
a message to a specific peer.
For example the PAIR version 1 protocol can do
this when NNG_OPT_PAIR1_POLY mode is set.
note
Not all protocols support overriding the destination pipe.
SEE ALSO
nng_msg_alloc, nng_msg_get_pipe
nng_msg_trim
NAME
nng_msg_trim — remove data from start of message body
SYNOPSIS
#include <nng/nng.h>
int nng_msg_trim(nng_msg *msg, size_t size);
int nng_msg_trim_u16(nng_msg *msg, uint16_t *val16);
int nng_msg_trim_u32(nng_msg *msg, uint32_t *val32);
int nng_msg_trim_u64(nng_msg *msg, uint64_t *val64);
DESCRIPTION
The nng_msg_trim() family of functions removes data from
the start of the body of message msg.
The first function removes size bytes.
The remaining functions remove 2, 4, or 8 bytes, and stores them in the value
(such as val32),
after converting them from network-byte order (big-endian) to native
byte order.
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_EINVAL: The message body is too short to remove the requested data.
SEE ALSO
nng_msg_alloc, nng_msg_append, nng_msg_body, nng_msg_capacity, nng_msg_chop nng_msg_clear, nng_msg_free, nng_msg_insert, nng_msg_len, nng_msg_reserve, nng_msg_realloc
Sockets
See Also
nng_bus_open, nng_close, nng_pair_open, nng_pub_open, nng_sub_open, nng_surveyor_open
nng_bus_open
NAME
nng_bus_open — create BUS socket
SYNOPSIS
#include <nng/nng.h>
#include <nng/protocol/bus0/bus.h>
int nng_bus0_open(nng_socket *s);
int nng_bus0_open_raw(nng_socket *s);
DESCRIPTION
The nng_bus0_open() function creates a BUS version 0
socket and returns it at the location pointed to by s.
The nng_bus0_open_raw() function creates a BUS version 0
socket in raw mode, and returns it at the location pointed to by s.
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol is not supported.
SEE ALSO
nng_close
NAME
nng_close — close socket
SYNOPSIS
#include <nng/nng.h>
int nng_close(nng_socket s);
DESCRIPTION
The nng_close() function closes the socket s.
Messages that have been submitted for sending may be flushed or delivered,
depending upon the transport.
Further attempts to use the socket after this call returns will result
in NNG_ECLOSED.
Threads waiting for operations on the socket when this
call is executed may also return with an NNG_ECLOSED result.
note
Closing the socket while data is in transmission will likely lead to loss
of that data.
There is no automatic linger or flush to ensure that the socket send buffers
have completely transmitted.
It is recommended to wait a brief period after calling
nng_send() or similar functions, before calling this
function.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_ECLOSED: The socket s is already closed or was never opened.
nng_device
NAME
nng_device - message forwarding device
SYNOPSIS
#include <nng/nng.h>
int nng_device(nng_socket s1, nng_socket s2);
void nng_device_aio(nng_aio *aio, nng_socket s1, nng_socket s2);
DESCRIPTION
The nng_device() and nng_device_aio() functions forward messages received from one
socket s1 to another socket s2, and vice versa.
These functions are used to create forwarders, which can be used to create complex network topologies to provide for improved horizontal scalability, reliability, and isolation.
Only raw mode sockets may be used with this
function.
These can be created using _raw forms of the various socket constructors,
such as nng_req0_open_raw().
The nng_device() function does not return until one of the sockets
is closed.
The nng_device_aio() function returns immediately, and operates completely in
the background.
Reflectors
One of the sockets passed may be an unopened socket initialized with
the NNG_SOCKET_INITIALIZER special value.
If this is the case, then the other socket must be valid, and must use
a protocol that is bidirectional and can peer with itself
(such as PAIR or BUS).
In this case the device acts as a reflector or loop-back device,
where messages received from the valid socket are merely returned
to the sender.
Forwarders
When both sockets are valid, then the result is a forwarder or proxy. In this case sockets s1 and s2 must be compatible with each other, which is to say that they should represent the opposite halves of a two protocol pattern, or both be the same protocol for a single protocol pattern. For example, if s1 is a PUB socket, then s2 must be a SUB socket. Or, if s1 is a BUS socket, then s2 must also be a BUS socket.
Operation
The nng_device() function moves messages between the provided sockets.
When a protocol has a backtrace style header, routing information is present in the header of received messages, and is copied to the header of the output bound message. The underlying raw mode protocols supply the necessary header adjustments to add or remove routing headers as needed. This allows replies to be returned to requesters, and responses to be routed back to surveyors.
The caller of these functions is required to close the sockets when the device is stopped.
Additionally, some protocols have a maximum time-to-live to protect
against forwarding loops and especially amplification loops.
In these cases, the default limit (usually 8), ensures that messages will
self-terminate when they have passed through too many forwarders,
protecting the network from unlimited message amplification that can arise
through misconfiguration.
This is controlled via the NNG_OPT_MAXTTL option.
note
Not all protocols have support for guarding against forwarding loops, and even for those that do, forwarding loops can be extremely detrimental to network performance.
note
Devices (forwarders and reflectors) act in best-effort delivery mode only. If a message is received from one socket that cannot be accepted by the other (due to back-pressure or other issues), then the message is discarded.
tip
Use the request/reply pattern, which includes automatic retries by the requester, if reliable delivery is needed.
RETURN VALUES
This function continues running, and only returns an appropriate error when one occurs, or if one of the sockets is closed.
ERRORS
NNG_ECLOSED: At least one of the sockets is not open.NNG_ENOMEM: Insufficient memory is available.NNG_EINVAL: The sockets are not compatible, or are both invalid.
SEE ALSO
nng_pair_open
NAME
nng_pair_open — create PAIR socket
SYNOPSIS
Version 0
#include <nng/protocol/pair0/pair.h>
int nng_pair0_open(nng_socket *s);
int nng_pair0_open_raw(nng_socket *s);
Version 1
#include <nng/protocol/pair1/pair.h>
int nng_pair1_open(nng_socket *s);
int nng_pair1_open_raw(nng_socket *s);
int nng_pair1_open_poly(nng_socktet *s);
DESCRIPTION
The nng_pair0_open() and nng_pair1_open() functions
create a PAIR version 0 or version 1
socket and return it at the location pointed to by s.
The nng_pair0_open_raw() and nng_pair1_open_raw() functions
create a PAIR version 0 or version 1 socket in
raw mode and return it at the location pointed to by s.
The nng_pair1_open_poly() function opens a pair version 1 socket in
polyamorous mode.
note
Polyamorous mode is deprecated and should not be used in new applications.
The nng_pair1_open_poly() function will likely be removed in a future release.
RETURN VALUES
These functions returns 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM:: Insufficient memory is available.NNG_ENOTSUP:: The protocol is not supported.
SEE ALSO
nng_pub_open
NAME
nng_pub_open — create PUB socket
SYNOPSIS
#include <nng/nng.h>
#include <nng/protocol/pubsub0/pub.h>
int nng_pub0_open(nng_socket *s);
int nng_pub0_open_raw(nng_socket *s);
DESCRIPTION
The nng_pub0_open() function creates a PUB version 0
socket and returns it at the location pointed to by s.
The nng_pub0_open_raw() function creates a PUB version 0
socket in
raw mode and returns it at the location pointed to by s.
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol is not supported.
SEE ALSO
Sockets PUB Protocol, SUB Protocol
nng_pull_open
NAME
nng_pull_open — create PULL socket
SYNOPSIS
#include <nng/nng.h>
#include <nng/protocol/pipeline0/pull.h>
int nng_pull0_open(nng_socket *s);
int nng_pull0_open_raw(nng_socket *s);
DESCRIPTION
The nng_pull0_open() function creates a PULL version 0
socket and returns it at the location pointed to by s.
The nng_pull0_open_raw() function creates a PULL version 0
socket in
raw mode and returns it at the location pointed to by s.
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol is not supported.
SEE ALSO
Sockets, PULL Protocol, PUSH Protocol
nng_push_open
NAME
nng_push_open — create PUSH socket
SYNOPSIS
#include <nng/nng.h>
#include <nng/protocol/pipeline0/push.h>
int nng_push0_open(nng_socket *s);
int nng_push0_open_raw(nng_socket *s);
DESCRIPTION
The nng_push0_open() function creates a PUSH version 0
socket and returns it at the location pointed to by s.
The nng_push0_open_raw() function creates a PUSH version 0 socket in
raw mode and returns it at the location pointed to by s.
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol is not supported.
SEE ALSO
Sockets, PULL Protocol, PUSH Protocol
nng_respondent_open
NAME
nng_respondent_open — create RESPONDENT socket
SYNOPSIS
#include <nng/nng.h>
#include <nng/protocol/survey0/respond.h>
int nng_respondent0_open(nng_socket *s);
int nng_respondent0_open_raw(nng_socket *s);
DESCRIPTION
The nng_respondent0_open() function creates a RESPONDENT
version 0 socket and returns it at the location
pointed to by s.
The nng_respondent0_open_raw() function creates a RESPONDENT
version 0 socket in raw mode and returns it at the location pointed to by s.
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol is not supported.
SEE ALSO
Sockets, RESPONDENT Protocol, SURVEYOR Protocol
nng_recv
NAME
nng_recv — recv data
SYNOPSIS
#include <nng/nng.h>
int nng_recv(nng_socket s, void *data, size_t *sizep, int flags);
DESCRIPTION
The nng_recv() receives a message from the socket s,
obtaining its body content.
The flags is a bit mask that may contain any of the following values:
-
NNG_FLAG_NONBLOCK:
The function returns immediately, even if no message is available. Without this flag, the function will wait until a message is received by the socket s, or any configured timer expires. -
NNG_FLAG_ALLOC:
If this flag is present, then a zero-copy mode is used. In this case the caller must set the value of data to the location of another pointer (of typevoid *), and the sizep pointer must be set to a location to receive the size of the message body. The function will then allocate a message buffer (as if bynng_alloc()), fill it with the message body, and store it at the address referenced by data, and update the size referenced by sizep. The caller is responsible for disposing of the received buffer either by thenng_free()function or passing the message (also with theNNG_FLAG_ALLOCflag) in a call tonng_send().
If the special flag NNG_FLAG_ALLOC (see above) is not specified, then the
caller must set data to a buffer to receive the message body content,
and must store the size of that buffer at the location pointed to by sizep.
When the function returns, if it is successful, the size at sizep will be
updated with the actual message body length copied into data.
note
The semantics of what receiving a message means vary from protocol to protocol, so examination of the protocol documentation is encouraged. Furthermore, some protocols may not support receiving data at all, or may require other conditions be met before they can receive.
tip
The NNG_FLAG_ALLOC flag can be used to reduce data copies, thereby
increasing performance, particularly if the buffer is reused to send
a response using the same flag. However, the nng_recvmsg() function is even better in this regard, and should be preferred over this
function when possible.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_EAGAIN: The operation would block, butNNG_FLAG_NONBLOCKwas specified.NNG_ECLOSED: The socket s is not open.NNG_EINVAL: An invalid set of flags was specified.NNG_EMSGSIZE: The received message did not fit in the size provided.NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol for socket s does not support receiving.NNG_ESTATE: The socket s cannot receive data in this state.NNG_ETIMEDOUT: The operation timed out.
SEE ALSO
nng_alloc, nng_free, nng_recvmsg, nng_send
nng_recv_aio
NAME
nng_recv_aio — receive message asynchronously
SYNOPSIS
#include <nng/nng.h>
void nng_recv_aio(nng_socket s, nng_aio *aio);
DESCRIPTION
The nng_recv_aio() function receives a message using the
socket s asynchronously.
When a message is successfully received by the socket, it is
stored in the aio by an internal call equivalent to
nng_aio_set_msg(), then the completion
callback on the aio is executed.
In this case, nng_aio_result() will
return zero.
The callback function is responsible for retrieving the message
and disposing of it appropriately.
important
Failing to dispose of successfully received messages will leak the memory associated with it.
If for some reason the asynchronous receive cannot be completed
successfully (including by being canceled or timing out), then
the callback will still be executed,
but nng_aio_result() will be non-zero.
note
The semantics of what receiving a message means varies from protocol to protocol, so examination of the protocol documentation is encouraged. Furthermore, some protocols may not support receiving or may require other conditions be met before receiving messages.
ERRORS
NNG_ECANCELED: The operation was aborted.NNG_ECLOSED: The socket s is not open.NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol for socket s does not support receiving.NNG_ESTATE: The socket s cannot receive data in this state.NNG_ETIMEDOUT: The receive timeout expired.
SEE ALSO
Messages, Sockets, Asynchronous I/O, nng_aio_get_msg, nng_msg_alloc
nng_recvmsg
NAME
nng_recvmsg — receive a message
SYNOPSIS
#include <nng/nng.h>
int nng_recvmsg(nng_socket s, nng_msg **msgp, int flags);
DESCRIPTION
The nng_recvmsg() receives a message on socket s, storing the
received message at the location pointed to by msgp.
This function gives access to the message structure, and thus may
offer more functionality than the simpler nng_recv() function.1 2
It is also more efficient.
An asynchronous form of this function is available as nng_recv_aio().
The flags may contain the following value:
NNG_FLAG_NONBLOCK:
The function returns immediately, even if no message is available. Without this flag, the function will wait until a message is received by the socket s, or any configured timer expires.
After successfully receiving a message, the caller is responsible for disposing of it when it is no longer needed.
important
Failing to dispose of the message will leak the memory associated with it.
note
The semantics of what receiving a message means vary from protocol to protocol, so examination of the protocol documentation is encouraged. Furthermore, some protocols do not support receiving data at all, or may require other conditions be met before receiving messages.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_EAGAIN: The operation would block, butNNG_FLAG_NONBLOCKwas specified.NNG_ECLOSED: The socket s is not open.NNG_EINVAL: An invalid set of flags was specified.NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol for socket s does not support receiving.NNG_ESTATE: The socket s cannot receive data in this state.NNG_ETIMEDOUT: The operation timed out.
SEE ALSO
Messages, Sockets, nng_msg_free, nng_recv, nng_sendmsg
nng_rep_open
NAME
nng_rep_open — create REP socket
SYNOPSIS
#include <nng/nng.h>
#include <nng/protocol/reqrep0/rep.h>
int nng_rep0_open(nng_socket *s);
int nng_rep0_open_raw(nng_socket *);
DESCRIPTION
The nng_rep0_open() function creates a REP version 0
socket and returns it at the location pointed to by s.
The nng_rep0_open_raw() function creates a REP version 0
socket in raw mode and returns it at the location pointed to by s.
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol is not supported.
SEE ALSO
Sockets, REP Protocol, REQ Protocol
nng_req_open
NAME
nng_req_open — create req socket
SYNOPSIS
#include <nng/nng.h>
#include <nng/protocol/reqrep0/req.h>
int nng_req0_open(nng_socket *s);
int nng_req0_open_raw(nng_socket *s);
DESCRIPTION
The nng_req0_open() function creates a REQ version 0
socket and returns it at the location pointed to by s.
The nng_req0_open_raw() function creates a REQ version 0
socket in raw mode and returns it at the location pointed to by s.
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol is not supported.
SEE ALSO
Sockets, REP Protocol, REQ Protocol
nng_send
NAME
nng_send — send data
SYNOPSIS
#include <nng/nng.h>
int nng_send(nng_socket s, void *data, size_t size, int flags);
DESCRIPTION
The nng_send() function sends a message containing the data of
length size using the socket s.
note
The semantics of what sending a message means vary from protocol to protocol, so examination of the protocol documentation is encouraged. For example, on PUB sockets the data is broadcast, so that any peers who have a suitable subscription will be able to receive it. Furthermore, some protocols may not support sending data or may require other conditions. For example, REP sockets cannot normally send data until they have first received a request.)
The flags may contain either of (or neither of) the following values:
-
NNG_FLAG_NONBLOCK:
The function returns immediately, regardless of whether the socket is able to accept the data or not. If the socket is unable to accept the data (such as if backpressure exists because the peers are consuming messages too slowly, or no peer is present), then the function will return withNNG_EAGAIN. If this flag is not specified, then the function will block if such a condition exists. -
NNG_FLAG_ALLOC:
The data was allocated usingnng_alloc(), or was obtained from a call tonng_recv()with theNNG_FLAG_ALLOCflag. If this function returns success, then the data is “owned” by the function, and it will assume responsibility for callingnng_free()when it is no longer needed. In the absence of this flag, the data is copied by the implementation before the function returns to the caller.
tip
The NNG_FLAG_ALLOC flag can be used to reduce data copies, thereby
increasing performance. However, the nng_sendmsg() function is even better in this regard, and should be preferred over this
function when possible.
note
Regardless of the presence or absence of NNG_FLAG_NONBLOCK, there may
be queues between the sender and the receiver.
Furthermore, there is no guarantee that the message has actually been delivered.
Finally, with some protocols, the semantic is implicitly NNG_FLAG_NONBLOCK,
such as with PUB sockets, which are best-effort delivery only.
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 teleportation of the program’s author to an alternate universe.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_EAGAIN: The operation would block, butNNG_FLAG_NONBLOCKwas specified.NNG_ECLOSED: The socket s is not open.NNG_EINVAL: An invalid set of flags was specified.NNG_EMSGSIZE: The value of size is too large.NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol for socket s does not support sending.NNG_ESTATE: The socket s cannot send data in this state.NNG_ETIMEDOUT: The operation timed out.
SEE ALSO
Sockets, nng_alloc, nng_free, nng_recv, nng_send_aio, nng_sendmsg
nng_send_aio
NAME
nng_send_aio — send message asynchronously
SYNOPSIS
#include <nng/nng.h>
void nng_send_aio(nng_socket s, nng_aio *aio);
DESCRIPTION
The nng_send_aio() sends a message using the
socket s asynchronously.
The message to send must have previously been set on the aio
using the nng_aio_set_msg() function.
The function assumes ownership of the message.
If the message was successfully queued for delivery to the socket,
then the aio will complete1, and nng_aio_result()
will return zero. In this case the socket will dispose of the
message when it is finished with it.
This does not indicate that the message was actually delivered, as it may still be buffered in the sending socket, buffered in the receiving socket, or in flight over physical media.
If the operation fails for any reason (including cancellation or timeout),
then the aio callback will be executed and
nng_aio_result() will return a non-zero error status.
In this case, the callback has a responsibility to retrieve the message from
the aio with
nng_aio_get_msg() and dispose of it appropriately. 2
(This may include retrying the send operation on the same or a different
socket, or deallocating the message with nng_msg_free().)
Failure to do so will leak the memory associated with the message.
note
The semantics of what sending a message means varies from protocol to protocol, so examination of the protocol documentation is encouraged. Furthermore, some protocols may not support sending, or may only permit sending when other conditions are met.
RETURN VALUES
None. (The operation completes asynchronously.)
ERRORS
NNG_ECANCELED: The operation was aborted.NNG_ECLOSED: The socket s is not open.NNG_EMSGSIZE: The message is too large.NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol for socket s does not support sending.NNG_ESTATE: The socket s cannot send data in this state.NNG_ETIMEDOUT: The send timeout expired.
SEE ALSO
Asynchronous I/O, Messages, Sockets, nng_aio_get_msg, nng_aio_set_msg, nng_msg_alloc
nng_sendmsg
NAME
nng_sendmsg — send message
SYNOPSIS
#include <nng/nng.h>
int nng_sendmsg(nng_socket s, nng_msg *msg, int flags);
DESCRIPTION
The nng_sendmsg() sends message msg using the socket s.
If the function returns zero, indicating it has accepted the message for delivery, then the msg is owned by the socket s, and the caller must not make any further use of it. The socket will free the message when it is finished.
If the function returns non-zero, then it is the caller’s responsibility to dispose of the msg, which may include freeing it, sending it to another socket, or simply trying again later.
tip
Using this function gives access to the message structure, and may
offer more functionality than the simpler nng_send() function. 1 2
It is also more efficient.
An asynchronous form of this function is available as nng_send_aio().
note
The semantics of what sending a message means vary from protocol to protocol, so examination of the protocol documentation is encouraged. Furthermore, some protocols may not support sending messages or may require other conditions be met first before sending messages.
The flags may contain the following value:
NNG_FLAG_NONBLOCK: The function returns immediately, regardless of whether the socket is able to accept the data or not. If the socket is unable to accept the data (such as if back-pressure exists because the peers are consuming messages too slowly, or no peer is present), then the function will return withNNG_EAGAIN. If this flag is not specified, then the function will block if such a condition exists.
note
Regardless of the presence or absence of NNG_FLAG_NONBLOCK, there may
be queues between the sender and the receiver.
Furthermore, there is no guarantee that the message has actually been delivered.
Finally, with some protocols, the semantic is implicitly NNG_FLAG_NONBLOCK,
such as with PUB sockets, which are best-effort delivery only.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_EAGAIN: The operation would block, butNNG_FLAG_NONBLOCKwas specified.NNG_ECLOSED: The socket s is not open.NNG_EINVAL: An invalid set of flags was specified.NNG_EMSGSIZE: The value of size is too large.NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol for socket s does not support sending.NNG_ESTATE: The socket s cannot send data in this state.NNG_ETIMEDOUT: The operation timed out.
SEE ALSO
Messages, Sockets, nng_msg_alloc, nng_recvmsg, nng_send
nng_sub_open
NAME
nng_sub_open - create SUB socket
SYNOPSIS
#include <nng/nng.h>
#include <nng/protocol/pubsub0/sub.h>
int nng_sub0_open(nng_socket *s);
int nng_sub0_open_raw(nng_socket *s);
DESCRIPTION
The nng_sub0_open() function creates a SUB version 0
socket and returns it at the location pointed to by s.
The nng_sub0_open_raw() function creates a SUB version 0
socket in
raw mode and returns it at the location pointed to by s.
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol is not supported.
SEE ALSO
Sockets, PUB Protocol, SUB Protocol
nng_surveyor_open
NAME
nng_surveyor_open — create SURVEYOR socket
SYNOPSIS
#include <nng/nng.h>
#include <nng/protocol/survey0/survey.h>
int nng_surveyor0_open(nng_socket *s);
int nng_surveyor0_open_raw(nng_socket *s);
DESCRIPTION
The nng_surveyor0_open() function creates a SURVEYOR
version 0 socket and returns it at the location
pointed to by s.
The nng_surveyor0_open_raw() function creates a SURVEYOR
version 0 socket in
raw mode and returns it at the location pointed to by s.
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol is not supported.
SEE ALSO
Sockets, RESPONDENT Protocol, SURVEYOR Protocol
nng_ctx
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][nng_dialer],
[listeners][nng_listener],
[pipes][nng_pipe],
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.
note
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.
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.
tip
Contexts are an excellent mechanism to use when building concurrent applications, and should be used in lieu of raw mode sockets when possible.
Caveats
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.
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.
Raw mode sockets do not support contexts, since there is generally no state tracked for them, and thus contexts make no sense.
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][nng_socket] has already been
created and any transports set up as well with functions such as
[nng_dial()][nng_dial] or nng_listen().
#define CONCURRENCY 1024
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(ec[i].ctx, rep_socket)
nng_aio_alloc(ec[i].aio, echo, &e[i]);
ec[i].state = INIT;
echo(&ec[i]); // start it running
}
}
SEE ALSO
nng_ctx_close, nng_ctx_open, nng_ctx_get, nng_ctx_id nng_ctx_recv, nng_ctx_recvmsg, nng_ctx_send, nng_ctx_sendmsg, nng_ctx_set, [nng_dialer][nng_dialer], [nng_listener][nng_listener], nng_socket, [nng_options][nng_options]
nng_ctx_close
NAME
nng_ctx_close — close context
SYNOPSIS
#include <nng/nng.h>
int nng_ctx_close(nng_ctx ctx);
DESCRIPTION
The nng_ctx_close() function closes the context ctx.
Messages that have been submitted for sending may be flushed or delivered,
depending upon the transport.
Further attempts to use the context after this call returns will result
in NNG_ECLOSED.
Threads waiting for operations on the context when this
call is executed may also return with an NNG_ECLOSED result.
note
Closing the socket associated with ctx
(using nng_close()) also closes this context.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_ECLOSED: The context ctx is already closed or was never opened.
SEE ALSO
nng_ctx_get
NAME
nng_ctx_get — get context option
SYNOPSIS
#include <nng/nng.h>
int nng_ctx_get(nng_ctx ctx, const char *opt, void *val, size_t *valszp);
int nng_ctx_get_bool(nng_ctx ctx, const char *opt, bool *bvalp);
int nng_ctx_get_int(nng_ctx ctx, const char *opt, int *ivalp);
int nng_ctx_get_ms(nng_ctx ctx, const char *opt, nng_duration *durp);
int nng_ctx_get_size(nng_ctx ctx, const char *opt, size_t *zp);
int nng_ctx_get_string(nng_ctx ctx, const char *opt, char **strp);
int nng_ctx_get_uint64(nng_ctx ctx, const char *opt, uint64_t *u64p);
DESCRIPTION
The nng_ctx_get() functions are used to retrieve option values for
the context ctx.
The actual options that may be retrieved in this way vary.
A number of them are documented in [nng_options][options].
note
Context options are protocol specific. The details will be documented with the protocol.
Forms
In all of these forms, the option opt is retrieved from the context ctx. The forms vary based on the type of the option they take.
The details of the type, size, and semantics of the option will depend on the actual option, and will be documented with the option itself.
-
nng_ctx_get():
This function is untyped and can be used to retrieve the value of any option. The caller must store a pointer to a buffer to receive the value in val, and the size of the buffer shall be stored at the location referenced by valszp.
When the function returns, the actual size of the data copied (or that would have been copied if sufficient space were present) is stored at the location referenced by valszp. If the caller’s buffer is not large enough to hold the entire object, then the copy is truncated. Therefore the caller should check for truncation by verifying that the returned size in valszp does not exceed the original buffer size.
It is acceptable to passNULLfor val if the value in valszp is zero. This can be used to determine the size of the buffer needed to receive the object. -
nng_ctx_get_bool():
This function is for options which take a Boolean (bool). The value will be stored at ivalp. -
nng_ctx_get_int():
This function is for options which take an integer (int). The value will be stored at ivalp. -
nng_ctx_get_ms():
This function is used to retrieve time durations (such as timeouts), stored in durp as a number of milliseconds. (The special valueNNG_DURATION_INFINITEmeans an infinite amount of time, and the special valueNNG_DURATION_DEFAULTmeans a context-specific default.) -
nng_ctx_get_size():
This function is used to retrieve a size into the pointer zp, typically for buffer sizes, message maximum sizes, and similar options. -
nng_ctx_get_string():
This function is used to retrieve a string into strp. This string is created from the source usingnng_strdup()and consequently must be freed by the caller usingnng_strfree()when it is no longer needed. -
nng_ctx_get_uint64():
This function is used to retrieve a 64-bit unsigned value into the value referenced by u64p. This is typically used for options related to identifiers, network numbers, and similar.
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_EBADTYPE: Incorrect type for option.NNG_ECLOSED: Parameter s does not refer to an open socket.NNG_EINVAL: Size of destination val too small for object.NNG_ENOMEM: Insufficient memory exists.NNG_ENOTSUP: The option opt is not supported.NNG_EWRITEONLY: The option opt is write-only.
SEE ALSO
nng_ctx_set, nng_strdup, nng_strfree, [nng_duration][nng_duration], [nng_options][options]
nng_ctx_getopt
NAME
nng_ctx_getopt — get context option (deprecated)
SYNOPSIS
#include <nng/nng.h>
int nng_ctx_getopt(nng_ctx ctx, const char *opt, void *val, size_t *valszp);
int nng_ctx_getopt_bool(nng_ctx ctx, const char *opt, bool *bvalp);
int nng_ctx_getopt_int(nng_ctx ctx, const char *opt, int *ivalp);
int nng_ctx_getopt_ms(nng_ctx ctx, const char *opt, nng_duration *durp);
int nng_ctx_getopt_size(nng_ctx ctx, const char *opt, size_t *zp);
int nng_ctx_getopt_string(nng_ctx ctx, const char *opt, char **strp);
int nng_ctx_getopt_uint64(nng_ctx ctx, const char *opt, uint64_t *u64p);
DESCRIPTION
important
These functions are deprecated. Please see nng_ctx_get.
They may not be present if the library was built with NNG_ELIDE_DEPRECATED.
They may also be removed entirely in a future version of NNG.
The nng_ctx_getopt() functions are used to retrieve option values for
the context ctx.
The actual options that may be retrieved in this way vary.
note
Context options are protocol specific. The details will be documented with the protocol.
Forms
In all of these forms, the option opt is retrieved from the context ctx. The forms vary based on the type of the option they take.
The details of the type, size, and semantics of the option will depend on the actual option, and will be documented with the option itself.
-
nng_ctx_getopt():
This function is untyped and can be used to retrieve the value of any option. The caller must store a pointer to a buffer to receive the value in val, and the size of the buffer shall be stored at the location referenced by valszp.
When the function returns, the actual size of the data copied (or that would have been copied if sufficient space were present) is stored at the location referenced by valszp. If the caller’s buffer is not large enough to hold the entire object, then the copy is truncated. Therefore the caller should check for truncation by verifying that the returned size in valszp does not exceed the original buffer size.
It is acceptable to passNULLfor val if the value in valszp is zero. This can be used to determine the size of the buffer needed to receive the object. -
nng_ctx_getopt_bool():
This function is for options which take a Boolean (bool). The value will be stored at ivalp. -
nng_ctx_getopt_int():
This function is for options which take an integer (int). The value will be stored at ivalp. -
nng_ctx_getopt_ms():
This function is used to retrieve time [durations][nng_duration] (such as timeouts), stored in durp as a number of milliseconds. (The special valueNNG_DURATION_INFINITEmeans an infinite amount of time, and the special valueNNG_DURATION_DEFAULTmeans a context-specific default.) -
nng_ctx_getopt_size():
This function is used to retrieve a size into the pointer zp, typically for buffer sizes, message maximum sizes, and similar options. -
nng_ctx_getopt_string():
This function is used to retrieve a string into strp. This string is created from the source usingnng_strdup()and consequently must be freed by the caller usingnng_strfree()when it is no longer needed. -
nng_ctx_getopt_uint64():
This function is used to retrieve a 64-bit unsigned value into the value referenced by u64p. This is typically used for options related to identifiers, network numbers, and similar.
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_EBADTYPE: Incorrect type for option.NNG_ECLOSED: Parameter s does not refer to an open socket.NNG_EINVAL: Size of destination val too small for object.NNG_ENOMEM: Insufficient memory exists.NNG_ENOTSUP: The option opt is not supported.NNG_EWRITEONLY: The option opt is write-only.
SEE ALSO
nng_strdup, nng_strfree, nng_duration, [nng_options][options]
nng_ctx_id
NAME
nng_ctx_id — return numeric context identifier
SYNOPSIS
#include <nng/nng.h>
int nng_ctx_id(nng_ctx c);
DESCRIPTION
The nng_ctx_id() function returns a positive identifier for the context c,
if it is valid.
Otherwise it returns -1.
note
A context is considered valid if it was ever opened with
nng_ctx_open() function.
Contexts that are allocated on the stack or statically should be
initialized with the macro NNG_CTX_INITIALIZER to ensure that
they cannot be confused with a valid context before they are opened.
RETURN VALUES
This function returns the positive value for the context identifier, or
-1 if the context is invalid.
nng_ctx_open
NAME
nng_ctx_open — create context
SYNOPSIS
#include <nng/nng.h>
int nng_ctx_open(nng_ctx *ctxp, nng_socket s);
DESCRIPTION
The nng_ctx_open() function creates a separate context to be used with
the socket s,
and returns it at the location pointed by ctxp.
note
Not every protocol supports creation of separate contexts.
Contexts allow the independent and concurrent use of stateful operations using the same socket. For example, two different contexts created on a REP socket can each receive requests, and send replies to them, without any regard to or interference with each other.
tip
Using contexts is an excellent way to write simpler concurrent applications, while retaining the benefits of the protocol-specific advanced processing, avoiding the need to bypass that with raw mode sockets.
note
Use of contexts with raw mode sockets is nonsensical, and not supported.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol does not support separate contexts, or the socket was opened in raw mode.
SEE ALSO
nng_ctx_close, nng_ctx_get, nng_ctx_recv, nng_ctx_send, nng_ctx_set, Sockets
nng_ctx_recv
NAME
nng_ctx_recv — receive message using context asynchronously
SYNOPSIS
#include <nng/nng.h>
void nng_ctx_recv(nng_ctx ctx, nng_aio *aio);
DESCRIPTION
The nng_ctx_recv() receives a message using the
context ctx asynchronously.
When a message is successfully received by the context, it is
stored in the aio by an internal call equivalent to
nng_aio_set_msg(), then the completion
callback on the aio is executed.
In this case, nng_aio_result() will
return zero.
The callback function is responsible for retrieving the message
and disposing of it appropriately.
important
Failing to accept and dispose of messages in this case can lead to memory leaks.
If for some reason the asynchronous receive cannot be completed
successfully (including by being canceled or timing out), then
the callback will still be executed,
but nng_aio_result() will be non-zero.
tip
The semantics of what receiving a message means varies from protocol to protocol, so examination of the protocol documentation is encouraged.
ERRORS
The following errors may be set on the aio, if the operation fails.
NNG_ECANCELED: The operation was aborted.NNG_ECLOSED: The context ctx is not open.NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol for context ctx does not support receiving.NNG_ESTATE: The context ctx cannot receive data in this state.NNG_ETIMEDOUT: The receive timeout expired.
SEE ALSO
nng_ctx_recvmsg
NAME
nng_ctx_recvmsg — receive message using socket
SYNOPSIS
#include <nng/nng.h>
int nng_ctx_recvmsg(nng_ctx ctx, nng_msg **msgp, int flags);
DESCRIPTION
The nng_ctx_recvmsg() receives a message on context ctx, storing the
received message at the location pointed to by msgp.
The flags may contain the following value:
NNG_FLAG_NONBLOCK:
The function returns immediately, even if no message is available. Without this flag, the function will wait until a message is receivable on the context ctx, or any configured timer expires.
tip
The semantics of what receiving a message means vary from protocol to protocol, so examination of the protocol documentation is encouraged.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_EAGAIN: The operation would block, butNNG_FLAG_NONBLOCKwas specified.NNG_ECLOSED: The context or socket is not open.NNG_EINVAL: An invalid set of flags was specified.NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol does not support receiving.NNG_ESTATE: The context cannot receive data in this state.NNG_ETIMEDOUT: The operation timed out.
SEE ALSO
nng_msg_free, nng_ctx_open, nng_ctx_recv, nng_ctx_sendmsg, Messages
nng_ctx_send
NAME
nng_ctx_send — send message using context asynchronously
SYNOPSIS
#include <nng/nng.h>
void nng_ctx_send(nng_ctx ctx, nng_aio *aio);
DESCRIPTION
The nng_ctx_send() sends a message using the
[context][nng_ctx] ctx asynchronously.
The message to send must have previously been set on the aio
using the nng_aio_set_msg() function.
The function assumes ownership of the message.
If the message was successfully queued for delivery to the socket,
then the aio will be completed, and nng_aio_result()
will return zero.
In this case the socket will dispose of the message when it is finished with it.
note
The operation will be completed, and the callback associated with the aio executed, as soon as the socket accepts the message for sending. This does not indicate that the message was actually delivered, as it may still be buffered in the sending socket, buffered in the receiving socket, or in flight over physical media.
If the operation fails for any reason (including cancellation or timeout),
then the aio callback will be executed and
nng_aio_result() will return a non-zero error status.
In this case, the callback has a responsibility to retrieve the message from
the aio with nng_aio_get_msg() and dispose of
it appropriately.
(This may include retrying the send operation on the same or a different
socket, or deallocating the message with nng_msg_free().
tip
The semantics of what sending a message means varies from protocol to protocol, so examination of the protocol documentation is encouraged.
ERRORS
NNG_ECANCELED: The operation was aborted.NNG_ECLOSED: The context ctx is not open.NNG_EMSGSIZE: The message is too large.NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol for context ctx does not support sending.NNG_ESTATE: The context ctx cannot send data in this state.NNG_ETIMEDOUT: The send timeout expired.
SEE ALSO
nng_aio_get_msg, nng_aio_set_msg, nng_ctx_sendmsg, nng_msg_alloc, nng_msg_free, Asynchronous I/O, Messages
nng_ctx_sendmsg()
NAME
nng_ctx_sendmsg — send message using context
SYNOPSIS
#include <nng/nng.h>
int nng_ctx_sendmsg(nng_ctx c, nng_msg *msg, int flags);
DESCRIPTION
The nng_ctx_sendmsg() sends message msg using the context ctx.
If the function returns zero, indicating it has accepted the message for delivery, then the msg is owned by the socket s, and the caller must not make any further use of it. The socket will free the message when it is finished.
If the function returns non-zero, then it is the caller’s responsibility to dispose of the msg, which may include freeing it, sending it to another socket, or simply trying again later.
tip
The semantics of what sending a message means vary from protocol to protocol, so examination of the protocol documentation is encouraged.
The flags may contain the following value:
NNG_FLAG_NONBLOCK:
The function returns immediately, regardless of whether the context is able to accept the data or not. If the context is unable to accept the data (such as if backpressure exists because the peers are consuming messages too slowly, or no peer is present), then the function will return withNNG_EAGAIN. If this flag is not specified, then the function will block if such a condition exists.1
Regardless of the presence or absence of NNG_FLAG_NONBLOCK, there may
be queues between the sender and the receiver.
Furthermore, there is no guarantee that the message has actually been delivered.
Finally, with some protocols, the semantic is implicitly NNG_FLAG_NONBLOCK.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_EAGAIN: The operation would block, butNNG_FLAG_NONBLOCKwas specified.NNG_ECLOSED: The context or socket is not open.NNG_EINVAL: An invalid set of flags was specified.NNG_EMSGSIZE: The value of size is too large.NNG_ENOMEM: Insufficient memory is available.NNG_ENOTSUP: The protocol does not support sending.NNG_ESTATE: The context cannot send data in this state.NNG_ETIMEDOUT: The operation timed out.
SEE ALSO
nng_ctx_set
NAME
nng_ctx_set — set context option
SYNOPSIS
#include <nng/nng.h>
int nng_ctx_set(nng_ctx ctx, const char *opt, const void *val, size_t valsz);
int nng_ctx_set_bool(nng_ctx ctx, const char *opt, int bval);
int nng_ctx_set_int(nng_ctx ctx, const char *opt, int ival);
int nng_ctx_set_ms(nng_ctx ctx, const char *opt, nng_duration dur);
int nng_ctx_set_size(nng_ctx ctx, const char *opt, size_t z);
int nng_ctx_set_string(nng_ctx ctx, const char *opt, const char *str);
int nng_ctx_set_uint64(nng_ctx ctx, const char *opt, uint64_t u64);
DESCRIPTION
The nng_ctx_set() functions are used to configure options for
the context ctx.
The actual options that may be configured in this way vary, and are
specified by opt.
note
Context options are protocol specific. The details will be documented with the protocol.
Forms
The details of the type, size, and semantics of the option will depend on the actual option, and will be documented with the option itself.
-
nng_ctx_set():
This function is untyped, and can be used to configure any arbitrary data. The val pointer addresses the data to copy, and valsz is the size of the objected located at val. -
nng_ctx_set_bool():
This function is for options which take a Boolean (bool). The bval is passed to the option. -
nng_ctx_set_int():
This function is for options which take an integer (int). The ival is passed to the option. -
nng_ctx_set_ms():
This function is used to configure time durations (such as timeouts) using type [nng_duration][nng_duration]. The duration dur is an integer number of milliseconds. -
nng_ctx_set_size():
This function is used to configure a size, z, typically for buffer sizes, message maximum sizes, and similar options. -
nng_ctx_set_string():
This function is used to pass configure a string, str. Strings passed this way must be legal UTF-8 or ASCII strings, terminated with aNUL(\0) byte. (Other constraints may apply as well, see the documentation for each option for details.) -
nng_ctx_set_uint64():
This function is used to configure a 64-bit unsigned value, u64. This is typically used for options related to identifiers, network numbers, and similar.
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_ECLOSED: Parameter s does not refer to an open socket.NNG_EINVAL: The value being passed is invalid.NNG_ENOTSUP: The option opt is not supported.NNG_EREADONLY: The option opt is read-only.NNG_ESTATE: The socket is in an inappropriate state for setting this option.
SEE ALSO
nng_ctx_get, [nng_socket_set][nng_socket_get], [Options][options]
nng_ctx_setopt
NAME
nng_ctx_setopt — set context option (deprecated)
SYNOPSIS
#include <nng/nng.h>
int nng_ctx_setopt(nng_ctx ctx, const char *opt, const void *val, size_t valsz);
int nng_ctx_setopt_bool(nng_ctx ctx, const char *opt, int bval);
int nng_ctx_setopt_int(nng_ctx ctx, const char *opt, int ival);
int nng_ctx_setopt_ms(nng_ctx ctx, const char *opt, nng_duration dur);
int nng_ctx_setopt_size(nng_ctx ctx, const char *opt, size_t z);
int nng_ctx_setopt_string(nng_ctx ctx, const char *opt, const char *str);
int nng_ctx_setopt_uint64(nng_ctx ctx, const char *opt, uint64_t u64);
DESCRIPTION
important
These functions are deprecated.
Please see nng_ctx_set().
They may not be present if the library was built with NNG_ELIDE_DEPRECATED.
They may also be removed entirely in a future version of NNG.
The nng_ctx_setopt() functions are used to configure options for
the context ctx.
The actual options that may be configured in this way vary, and are
specified by opt.
note
Context options are protocol specific. The details will be documented with the protocol.
Forms
The details of the type, size, and semantics of the option will depend on the actual option, and will be documented with the option itself.
-
nng_ctx_setopt():
This function is untyped, and can be used to configure any arbitrary data. The val pointer addresses the data to copy, and valsz is the size of the objected located at val. -
nng_ctx_setopt_bool():
This function is for options which take a Boolean (bool). The bval is passed to the option. -
nng_ctx_setopt_int():
This function is for options which take an integer (int). The ival is passed to the option. -
nng_ctx_setopt_ms():
This function is used to configure time durations (such as timeouts) using type [nng_duration][nng_duration]. The duration dur is an integer number of milliseconds. -
nng_ctx_setopt_size():
This function is used to configure a size, z, typically for buffer sizes, message maximum sizes, and similar options. -
nng_ctx_setopt_string():
This function is used to pass configure a string, str. Strings passed this way must be legal UTF-8 or ASCII strings, terminated with aNUL(\0) byte. (Other constraints may apply as well, see the documentation for each option for details.) -
nng_ctx_setopt_uint64():
This function is used to configure a 64-bit unsigned value, u64. This is typically used for options related to identifiers, network numbers, and similar.
RETURN VALUES
These functions return 0 on success, and non-zero otherwise.
ERRORS
NNG_ECLOSED: Parameter s does not refer to an open socket.NNG_EINVAL: The value being passed is invalid.NNG_ENOTSUP: The option opt is not supported.NNG_EREADONLY: The option opt is read-only.NNG_ESTATE: The socket is in an inappropriate state for setting this option.
SEE ALSO
nng_ctx_set, [Options][options]
Aysnchronous I/O
NNG provides rich support for asynchronous I/O. This allows applications to achieve high levels of concurrency with a minimum of fuss, optimized for the platform.
Asynchronous I/O is performed without blocking calling application threads, so they may continue to perform other work.
AIO Handles
Applications create an nng_aio object with a function to call when
the operation is done (along with a pointer to application private data),
then submit the operation.
These nng_aio objects are created using the nng_aio_alloc(),
and destroyed using nng_aio_free().
The nng_aio object itself is declared like this:
#include <nng/nng.h>
typedef struct nng_aio nng_aio;
Every asynchronous operation uses its own instance an nng_aio, and each
nng_aio can only be used with a single operation at a time.
important
Attempting to submit an operation using an nng_aio that is already
in use for another operation will crash the application.
However, it is possible to submit another operation on the nng_aio from
the callback associated with the same nng_aio.
When the operation is complete, whether successfully or otherwise, the callback function is executed. The callback will be executed exactly once.
Cancellation
The asynchronous I/O framework also supports cancellation of
operations that are already in progress
(see nng_aio_cancel()), as well setting a maximum
timeout for them to complete within
(see nng_aio_set_timeout()).
Waiting for Completion
It is also possible to initiate an asynchronous operation, and wait for it to
complete nng_aio_wait().
important
Applications must never call nng_aio_wait() or
nng_aio_stop() from a callback registered to
an nng_aio object. Doing so can lead to a deadlock.
See Also
nng_aio_abort, nng_aio_alloc, nng_aio_cancel, nng_aio_count, nng_aio_free, nng_aio_get_input, nng_aio_get_msg, nng_aio_get_output, nng_aio_result, nng_aio_set_input, nng_aio_set_iov, nng_aio_set_msg, nng_aio_set_timeout, nng_aio_stop, nng_aio_wait
nng_aio_abort
NAME
nng_aio_abort — abort asynchronous I/O operation
SYNOPSIS
#include <nng/nng.h>
void nng_aio_abort(nng_aio *aio, int err);
DESCRIPTION
The nng_aio_abort() function aborts an operation previously started
with the handle aio.
If the operation is aborted, then the callback
for the handle will be called, and the function
nng_aio_result()
will return the error err.
This function does not wait for the operation to be fully aborted, but returns immediately.
If no operation is currently in progress (either because it has already finished, or no operation has been started yet), then this function has no effect.
SEE ALSO
nng_aio_alloc, nng_aio_cancel, nng_aio_result
nng_aio_alloc
NAME
nng_aio_alloc — allocate asynchronous I/O handle
SYNOPSIS
#include <nng/nng.h>
int nng_aio_alloc(nng_aio **aiop, void (*callb)(void *), void *arg);
DESCRIPTION
The nng_aio_alloc() function allocates a handle for asynchronous I/O
operations, and stores a pointer to it in the location referenced by aiop.
The handle is initialized with a completion callback of callb,
which will be executed when an associated asynchronous operation finishes.
It will be called with the argument arg.
important
The callback callb must not perform any blocking operations, and must complete its execution quickly. If callb does block, this can lead ultimately to an apparent “hang” or deadlock in the application. This also means you should avoid operations such as allocating new objects, which also means opening or closing sockets, dialers, and so forth.
tip
If more complex or blocking work needs to be performed by callb, a separate thread can be used, along with a condition variable which can be signaled by the callback.
Asynchronous I/O operations all take an nng_aio
handle such as allocated by this function.
Such operations are usually started by a function that returns immediately.
The operation is then run asynchronously, and completes sometime later.
When that operation is complete, the callback supplied here is called,
and that callback is able to determine the result of the operation using
nng_aio_result(), nng_aio_count(),
and nng_aio_get_output().
It is possible to wait synchronously for an otherwise asynchronous operation
by using the function nng_aio_wait().
In that case, it is permissible for callb and arg to both be NULL.
Note that if these are NULL, then it will not be possible to determine when the
operation is complete except by calling the aforementioned
nng_aio_wait().
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient free memory to perform the operation.
SEE ALSO
nng_aio_abort, nng_aio_cancel, nng_aio_count, nng_aio_free, nng_aio_get_msg, nng_aio_get_output, nng_aio_result, nng_aio_set_input, nng_aio_set_iov, nng_aio_set_msg, nng_aio_set_timeout, nng_aio_stop, nng_aio_wait
nng_aio_busy
NAME
nng_aio_busy — test if asynchronous I/O is busy
SYNOPSIS
#include <nng/nng.h>
bool nng_aio_busy(nng_aio *aio);
DESCRIPTION
The nng_aio_busy() function returns true if the
aio is currently busy performing an asynchronous I/O
operation or is executing a completion callback.
If no operation has been started, or the operation has been completed or canceled, and any callback has been executed, then it returns false.
This is the same test used internally by
nng_aio_wait().
important
Care should be taken to ensure that the aio object is not freed when using this function. The caller is responsible for coordinating any use of this with any reuse of the aio.
RETURN VALUES
True if the aio is busy, false otherwise.
SEE ALSO
nng_aio_abort, nng_aio_alloc, nng_aio_wait
nng_aio_cancel
NAME
nng_aio_cancel — cancel asynchronous I/O operation
SYNOPSIS
#include <nng/nng.h>
void nng_aio_cancel(nng_aio *aio);
DESCRIPTION
The nng_aio_cancel() function aborts an operation previously started
with the handle aio.
If the operation is aborted, then the callback
for the handle will be called, and the function
nng_aio_result() will return the error NNG_ECANCELED.
This function does not wait for the operation to be fully aborted, but returns immediately.
If no operation is currently in progress (either because it has already finished, or no operation has been started yet), then this function has no effect.
This function is the same as calling
nng_aio_abort() with the error NNG_ECANCELED.
SEE ALSO
nng_aio_abort, nng_aio_alloc, nng_aio_result
nng_aio_count
NAME
nng_aio_count — return number of bytes transferred
SYNOPSIS
#include <nng/nng.h>
size_t nng_aio_count(nng_aio *aio);
DESCRIPTION
The nng_aio_count() returns the number of bytes transferred by the
asynchronous operation associated with the handle aio.
Some asynchronous operations do not provide meaningful data for this function; for example operations that establish connections do not transfer user data (they may transfer protocol data though) – in this case this function will generally return zero.
This function is most useful when used with operations that make use of
of a scatter/gather vector (set by nng_aio_set_iov()).
note
The return value from this function is undefined if the operation
has not completed yet.
Either call this from the handle’s completion callback,
or after waiting for the operation to complete with
nng_aio_wait().
RETURN VALUES
The number of bytes transferred by the operation.
SEE ALSO
nng_aio_alloc, nng_aio_result, nng_aio_set_iov, nng_aio_wait
nng_aio_free
NAME
nng_aio_free — free asynchronous I/O handle
SYNOPSIS
#include <nng/nng.h>
void nng_aio_free(nng_aio *aio);
void nng_aio_reap(nng_aio *aio);
DESCRIPTION
The nng_aio_free() function frees an allocated asynchronous I/O handle.
If any operation is in progress, the operation is canceled, and the
caller is blocked until the operation is completely canceled, to ensure
that it is safe to deallocate the handle and any associated resources.
(This is done by implicitly calling nng_aio_stop().)
The nng_aio_reap() function is the same as nng_aio_free(), but does
its work in a background thread.
This can be useful to discard the aio object from within the callback for the aio.
important
Once either of these functions are called, the aio object is invalid and must not be used again.
SEE ALSO
nng_aio_get_msg
NAME
nng_aio_get_msg — get message from asynchronous receive
SYNOPSIS
#include <nng/nng.h>
nng_msg *nng_aio_get_msg(nng_aio *aio);
DESCRIPTION
The nng_aio_get_msg() function gets any message stored in aio as
either a result of a successful receive
(see nng_recv_aio())
or that was previously stored with
nng_aio_set_msg().
important
The aio must not have an operation in progress.
SEE ALSO
nng_aio_set_msg, nng_recv_aio, Messages
nng_aio_get_output
NAME
nng_aio_get_output — return output result
SYNOPSIS
#include <nng/nng.h>
void *nng_aio_get_output(nng_aio *aio, unsigned int index);
DESCRIPTION
The nng_aio_get_output() function returns the output result at index
resulting from the asynchronous operation associated with aio.
The type and semantics of output parameters are determined by specific operations.
note
If the index does not correspond to a defined output for the operation,
or the operation did not succeed, then the return value will be NULL.
important
It is an error to call this function while the aio is currently in use by an active asynchronous operation, or if no operation has been performed using the aio yet.
RETURN VALUES
The indexth output from the operation, or NULL.
SEE ALSO
nng_aio_alloc, nng_aio_set_output, nng_aio_result
nng_aio_result
NAME
nng_aio_result — return result of asynchronous operation
SYNOPSIS
#include <nng/nng.h>
int nng_aio_result(nng_aio *aio);
DESCRIPTION
The nng_aio_result() returns the result of the operation associated
with the handle aio.
If the operation was successful, then 0 is returned.
Otherwise a non-zero error code is returned.
note
The return value from this function is undefined if the operation
has not completed yet.
Either call this from the handle’s completion
callback, or after waiting for the operation to complete with
nng_aio_wait().
RETURN VALUES
The result of the operation, either zero on success, or an error number on failure.
ERRORS
NNG_ETIMEDOUT: The operation timed out.NNG_ECANCELED: The operation was canceled.
Various other return values are possible depending on the operation.
SEE ALSO
nng_aio_abort, nng_aio_alloc, nng_aio_wait, nng_strerror
nng_aio_set_input
NAME
nng_aio_set_input — set input parameter
SYNOPSIS
#include <nng/nng.h>
void nng_aio_set_input(nng_aio *aio, unsigned int index, void *param);
DESCRIPTION
The nng_aio_set_input() function sets the input parameter at index
to param for the asynchronous operation associated with aio.
The type and semantics of input parameters are determined by specific operations; the caller must supply appropriate inputs for the operation to be performed.
The valid values of index range from zero (0) to three (3), as no operation currently defined can accept more than four parameters. (This limit could increase in the future.)
note
If the index does not correspond to a defined input for the operation, then this function will have no effect.
important
It is an error to call this function while the aio is currently in use by an active asynchronous operation.
An input parameter set with this function may be retrieved later with
the nng_aio_get_input() function.
SEE ALSO
nng_aio_alloc, nng_aio_get_input
nng_aio_set_iov()
NAME
nng_aio_set_iov — set scatter/gather vector
SYNOPSIS
#include <nng/nng.h>
int nng_aio_set_iov(nng_aio *aio, unsigned int niov, nng_iov *iov);
DESCRIPTION
The nng_aio_set_iov() function sets a scatter/gather vector iov on the handle aio.
The iov is a pointer to an array of niov [nng_iov][nng_iov]
structures, which have the following definition:
typedef struct nng_iov {
void * iov_buf;
size_t iov_len;
};
The iov is copied into storage in the aio itself, so that callers may use stack allocated nng_iov structures.
The values pointed to by the iov_buf members are not copied by this function though.
A maximum of four (4) nng_iov members may be supplied.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_EINVAL: Value of specified niov is too large.
nng_aio_set_msg()
NAME
nng_aio_set_msg — set message for asynchronous send
SYNOPSIS
#include <nng/nng.h>
void nng_aio_set_msg(nng_aio *aio, nng_msg *msg);
DESCRIPTION
The nng_aio_set_msg() function sets the message that will be used
for an asynchronous send operation (see
nng_send_aio()).
important
The aio must not have an operation in progress.
SEE ALSO
nng_aio_get_msg, nng_send_aio, Messages
nng_aio_set_timeout
NAME
nng_aio_set_timeout — set asynchronous I/O timeout
SYNOPSIS
#include <nng/nng.h>
typedef int nng_duration;
void nng_aio_set_timeout(nng_aio *aio, nng_duration timeout);
typedef uint64_t nng_time;
void nng_aio_set_expire(nng_aio *aio, nng_time expiration);
DESCRIPTION
The nng_aio_set_timeout() function sets a timeout
for the asynchronous operation associated with aio.
This causes a timer to be started when the operation is actually started.
If the timer expires before the operation is completed, then it is
aborted with an error of NNG_ETIMEDOUT.
The timeout is specified as a relative number of milliseconds.
If the timeout is NNG_DURATION_INFINITE, then no timeout is used.
If the timeout is NNG_DURATION_DEFAULT, then a “default” or socket-specific
timeout is used.
(This is frequently the same as NNG_DURATION_INFINITE.)
The nng_aio_set_expire() function is similar to nng_aio_set_timeout(), but sets
an absolute expiration time based on the system clock. The expiration
is expressed as a number of milliseconds since some point in the past.
The nng_clock() function can be used to determine
the current value of the clock.
tip
As most operations involve some context switching, it is usually a good idea to allow at least a few tens of milliseconds before timing them out – a too small timeout might not allow the operation to properly begin before giving up!
The value of timeout set for the aio is persistent, so that if the handle is reused for future operations, it will have the same relative or absolute timeout.
SEE ALSO
nng_aio_cancel, nng_aio_result, nng_clock
nng_aio_stop
NAME
nng_aio_stop - stop asynchronous I/O operation
SYNOPSIS
#include <nng/nng.h>
void nng_aio_stop(nng_aio *aio);
DESCRIPTION
The nng_aio_stop() function stops the asynchronous I/O operation
associated with aio by aborting with NNG_ECANCELED, and then waits
for it to complete or to be completely aborted, and for the
callback associated with the aio to have completed executing.
Further calls to
nng_aio_begin() using this aio will return false.
It is safe to call this for an aio, even when no operation is currently pending for it.
tip
When multiple asynchronous I/O handles are in use and need to be
shut down, it is safest to stop all of them, before deallocating any of
them with nng_aio_free(), particularly if the callbacks
might attempt to reschedule additional operations.
SEE ALSO
nng_aio_cancel, nng_aio_free, nng_aio_wait
nng_aio_wait
NAME
nng_aio_wait — wait for asynchronous I/O operation
SYNOPSIS
#include <nng/nng.h>
void nng_aio_wait(nng_aio *aio);
DESCRIPTION
The nng_aio_wait() function waits for an asynchronous I/O operation
to complete.
If the operation has not been started, or has already
completed, then it returns immediately.
If a callback was set with aio when it was allocated, then this function will not be called until the callback has completed.
important
This function should never be called from a function that itself
is a callback of an nng_aio, either this one or any other.
Doing so may result in a deadlock.
SEE ALSO
Asynchronous I/O for Providers
I/O providers perform the operations that are linked to
an nng_aio object, on behalf of applications
that submit requests for the same operations.
Most applications will not use the functions listed here. Applications that implement their own HTTP handler functions, or custom transport providers, might make use of these functions.
In addition to these functions, I/O providers may utilize the other consumer functions for Aysnchronous I/O.
See Also
nng_aio_begin, nng_aio_defer, nng_aio_finish, nng_aio_get_input, nng_aio_set_output, Asynchronous I/O
nng_aio_begin
NAME
nng_aio_begin — begin asynchronous I/O operation
SYNOPSIS
#include <nng/nng.h>
bool nng_aio_begin(nng_aio *aio);
DESCRIPTION
The nng_aio_begin() function is called by the I/O provider to indicate that
it is going to process the operation.
The function may return false, indicating that the aio has been closed.
In this case the provider should abandon the operation and do nothing else.
This operation should be called at the start of any I/O operation, and must be called not more than once for a given I/O operation on a given aio.
Once this function is called, if true is returned, then the provider MUST
guarantee that nng_aio_finish() is called for the aio
exactly once, when the operation is complete or canceled.
tip
This function is only for I/O providers (those actually performing the operation such as HTTP handler functions or transport providers); ordinary users of the aio should not call this function.
RETURN VALUES
true: The operation has been started.false: The operation cannot be started.
SEE ALSO
nng_aio_cancel, nng_aio_defer, nng_aio_finish
nng_aio_defer
NAME
nng_aio_defer — defer asynchronous I/O operation
SYNOPSIS
#include <nng/nng.h>
typedef void (*nng_aio_cancelfn)(nng_aio *aio, void *arg, int err);
void nng_aio_defer(nng_aio *aio, nng_aio_cancelfn fn, void *arg);
DESCRIPTION
The nng_aio_defer() function marks operation associated with aio as
being deferred for asynchronous completion, registering a cancellation
function fn and associated argument arg.
This permits the operation to be canceled.
If the aio is canceled, the cancellation routine fn will be called
with the aio, the arg specified by nng_aio_defer(), and an error
value in err, which is the reason that the operation is being canceled.
At any given time, the operation may not be cancelable. For example it may have already been completed, or be in a state where it is no longer possible to unschedule it. In this case, the cancelfn should just return without making any changes.
If the cancellation routine successfully canceled the operation, it should
ensure that nng_aio_finish() is called, with the
error code specified by err.
important
It is mandatory that I/O providers call nng_aio_finish() exactly once when they are finished with the operation.
important
Care must be taken to ensure that cancellation and completion of the routine are multi-thread safe. This will usually involve the use of locks or other synchronization primitives.
tip
For operations that complete synchronously, without any need to be
deferred, the provider need not call nng_aio_defer().
tip
This function is only for I/O providers (those actually performing the operation such as HTTP handler functions or transport providers); ordinary users of the aio should not call this function.
SEE ALSO
nng_aio_alloc, nng_aio_cancel, nng_aio_finish
nng_aio_finish
NAME
nng_aio_finish — finish asynchronous I/O operation
SYNOPSIS
#include <nng/nng.h>
void nng_aio_finish(nng_aio *aio, int err);
DESCRIPTION
The nng_aio_finish() function marks operation associated with aio as
complete, with the status err.
This will be the result returned by nng_aio_result().
This function causes the callback associated with the aio to called.
important
It is mandatory that operation providers call this function exactly once when they are finished with the operation. After calling this function, the provider must not perform any further accesses to the aio.
tip
This function is only for I/O providers (those actually performing the operation such as HTTP handler functions or transport providers); ordinary users of the aio should not have any need for this function.
SEE ALSO
nng_aio_begin, nng_aio_cancel, nng_aio_defer, nng_aio_result
nng_aio_get_input
NAME
nng_aio_get_input — return input parameter
SYNOPSIS
#include <nng/nng.h>
void *nng_aio_get_input(nng_aio *aio, unsigned int index);
DESCRIPTION
The nng_aio_get_input() function returns the value of the input parameter
previously set at index on aio with the
nng_aio_set_input()function.
The valid values of index range from zero (0) to three (3), as no operation
currently defined can accept more than four parameters.
If the index supplied is outside of this range,
or if the input parameter was not previously set, then NULL is returned.
RETURN VALUES
Value previously set, or NULL.
SEE ALSO
nng_aio_alloc, nng_aio_get_output, nng_aio_set_input
nng_aio_set_output
NAME
nng_aio_set_output — set output result
SYNOPSIS
#include <nng/nng.h>
void nng_aio_set_output(nng_aio *aio, unsigned int index, void *result);
DESCRIPTION
The nng_aio_set_output() function sets the output result at index
to result for the asynchronous operation associated with aio.
The type and semantics of output results are determined by specific operations; the operation must supply appropriate output results when the operation completes successfully.
The valid values of index range from zero (0) to three (3), as no operation currently defined can return more than four results.
note
Note that attempts to set results with an index greater than three (3) will be ignored.
An output result set with this function may be retrieved later with
the nng_aio_get_output() function.
SEE ALSO
General Purpose Functions
See Also
nng_alloc, nng_clock, nng_free, nng_random, nng_version
nng_alloc
NAME
nng_alloc — allocate memory
SYNOPSIS
#include <nng/nng.h>
void *nng_alloc(size_t size);
DESCRIPTION
The nng_alloc() function allocates a contiguous memory region of
at least size bytes.
The memory will be 64-bit aligned.
The returned memory can be used to hold message buffers, in which
case it can be directly passed to nng_send() using
the flag NNG_FLAG_ALLOC. Alternatively, it can be freed when no
longer needed using nng_free().
important
Do not use the system free() function (or the C++ delete operator) to release this memory.
On some configurations this may work, but on others it will lead to a crash or
other unpredictable behavior.
RETURN VALUES
This function returns a pointer to the allocated memory on success,
and NULL otherwise.
ERRORS
No errors are returned, but if memory cannot be allocated then NULL
is returned.
SEE ALSO
nng_clock
NAME
nng_clock - get time
SYNOPSIS
#include <nng/nng.h>
#include <nng/supplemental/util/platform.h>
typedef uint64_t nng_time;
nng_time nng_clock(void);
DESCRIPTION
The nng_clock() function returns the number of elapsed milliseconds since some
arbitrary time in the past.
The resolution of the clock depends on the underlying timing facilities
of the system.
This function may be used for timing, but applications should not expect
very fine-grained values.
note
The reference time will be the same for a given program, but different programs may have different references.
This function is intended to help with setting appropriate
timeouts using nng_cv_until()
or nng_aio_set_expire().
RETURN VALUES
Milliseconds since reference time.
SEE ALSO
nng_sleep_aio, nng_cv_until, nng_msleep, nng_duration
nng_free
NAME
nng_free — free memory
SYNOPSIS
#include <nng/nng.h>
void nng_free(void *ptr, size_t size);
DESCRIPTION
The nng_free() function deallocates a memory region of size size,
that was previously allocated by nng_alloc() or
nng_recv() with the NNG_FLAG_ALLOC flag.
important
It is very important that size match the allocation size used to allocate the memory.
important
Do not attempt to use this function to deallocate memory
obtained by a call to the system malloc() or calloc() functions,
or the C++ new operator.
Doing so may result in unpredictable
behavior, including corruption of application memory.
SEE ALSO
nng_id_map
NAME
nng_id_map — identifier based mapping table
SYNOPSIS
#include <nng/nng.h>
#include <nng/supplemental/util/idhash.h>
typedef struct nng_id_map_s nng_id_map;
#define NNG_MAP_RANDOM 1
int nng_id_map_alloc(nng_id_map **map_p, uint64_t lo, uint64_t hi, int flags);
void nng_id_map_free(nng_id_map *map);
void *nng_id_get(nng_id_map *map, uint64_t id);
int nng_id_set(nng_id_map *map, uint64_t, void *value);
int nng_id_alloc(nng_id_map *map, uint64_t *id_p, void *value);
int nng_id_remove(nng_id_map *map, uint64_t id);
DESCRIPTION
These functions provide support for managing tables of data based on identifiers, ensuring that identifiers are allocated uniquely and within specified range limits.
The table stores data pointers (which must not be NULL) at a logical numeric index.
It does so efficiently, even if large gaps exist, and it provides a means to efficiently
allocate a numeric identifier from a pool of unused identifiers.
Identifiers are allocated in increasing order, without reusing old identifiers until the largest possible identifier is allocated. After wrapping, only identifiers that are no longer in use will be considered. No effort is made to order the availability of identifiers based on when they were freed.1
The concern about possibly reusing a recently released identifier comes into consideration after the range has wrapped. Given a sufficiently large range, this is unlikely to be a concern.
An initial table is allocated with nng_id_map_alloc(), which takes the lowest legal identifier in lo,
and the largest legal identifier in hi.
The new table is returned in map_p, and should be used as the map argument to the rest of these functions.
If these lo and hi are both zero, then a full range of 32-bit identifiers is assumed.2
Consequently, if identifiers larger than or equal to 232 are required, then both lo and hi must be specified with the exact values desired.
The flags argument is a bit mask of flags for the table.
If NNG_MAP_RANDOM is specified, then the starting point for allocations is randomized, but subsequent allocations will then be monotonically increasing.
This is useful to reduce the odds of different instances of an application using the same identifiers at the same time.
The nng_id_get() function returns the value previously stored with the given identifier.
If no value is currently associated with the identifer, it returns NULL.
The nng_id_set() function sets the value with the associated identifier.
This can be used to replace a previously allocated identifier.
If the identifier was not previously allocated, then it is allocated as part of the call.
This function does not necessarily honor the identifier range limits set for the map when it was allocated.
The nng_id_alloc() function allocates a new identifier from the range for the map, and associates it with
the supplied value.
The nng_id_remove() function removes the identifier and its associated value from the table.
note
These functions are limited to storing at most 232 used identifiers, even though the identifers may themselves be larger than 232.
note
These functions are not thread-safe. Callers should use a [mutex][mutex] or similar approach when thread-safety is needed.
RETURN VALUES
The nng_id_map_alloc(), nng_id_set(), nng_id_alloc(), and nng_id_remove() functions
return 0 on success, or -1 on failure.
The nng_id_map_get() function returns the requested data pointer, or NULL if the identifier was not found.
ERRORS
NNG_ENOENT: The id does not exist in the table.NNG_ENOMEM: Insufficient memory is available, or the table is full.
nng_msleep
NAME
nng_msleep — sleep milliseconds
SYNOPSIS
#include <nng/nng.h>
#include <nng/supplemental/util/platform.h>
void nng_msleep(nng_duration msec);
DESCRIPTION
The nng_msleep() blocks the caller for at least msec milliseconds.
note
This function may block for longer than requested. The actual wait time is determined by the capabilities of the underlying system.
SEE ALSO
nng_random
NAME
nng_random — get random number
SYNOPSIS
#include <nng/nng.h>
#include <nng/supplemental/util/platform.h>
uint32_t nng_random(void);
DESCRIPTION
The nng_random() returns a random number.
The value returned is suitable for use with cryptographic functions such as
key generation.
The value is obtained using platform-specific cryptographically strong random
number facilities when available.
RETURN VALUES
Returns a random 32-bit value.
nng_sleep_aio
NAME
nng_sleep_aio - sleep asynchronously
SYNOPSIS
#include <nng/nng.h>
void nng_sleep_aio(nng_duration msec, nng_aio *aio);
DESCRIPTION
The nng_sleep_aio() function provides an asynchronous delay mechanism,
causing the callback for aio to be executed after msec milliseconds.
If the sleep finishes completely, the result will always be zero.
note
If a timeout is set on aio using
nng_aio_set_timeout(), and it is shorter
than msec,
then the sleep will wake up early, with a result code of NNG_ETIMEDOUT.
SEE ALSO
nng_clock, nng_msleep, Asynchronous I/O
nng_socket_pair
NAME
nng_socket_pair — create a connected pair of BSD sockets
SYNOPSIS
#include <nng/nng.h>
#include <nng/supplemental/util/platform.h>
int nng_socket_pair(int fds[2]);
DESCRIPTION
The nng_socket_pair() function creates a pair of connected BSD sockets.
These sockets, which are returned in the fds array, are suitable for
use with the BSD Socket transport.
On POSIX platforms, this is a thin wrapper around the standard socketpair() function,
using the AF_UNIX family and the SOCK_STREAM socket type.1
At present only POSIX platforms implementing socketpair() support this function.
tip
This function may be useful for creating a shared connection between a parent process and a child process on UNIX platforms, without requiring the processes use a shared filesystem or TCP connection.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient memory exists.NNG_ENOTSUP: This platform does not support socket pairs.
SEE ALSO
nng_strdup
NAME
nng_strdup — duplicate string
SYNOPSIS
#include <nng/nng.h>
char *nng_strdup(const char *src);
DESCRIPTION
The nng_strdup() duplicates the string src and returns it.
This is logically equivalent to using nng_alloc()
to allocate a region of memory of strlen(s) + 1 bytes, and then
using strcpy() to copy the string into the destination before
returning it.
The returned string should be deallocated with
nng_strfree(), or may be deallocated using the
nng_free() using the length of the returned string plus
one (for the NUL terminating byte).
important
Do not use the system free() or similar functions to deallocate
the string, since those may use a different memory arena!
RETURN VALUES
This function returns the new string on success, and NULL on failure.
ERRORS
No errors are returned, but a NULL return value should be
treated the same as NNG_ENOMEM.
SEE ALSO
nng_alloc.md, nng_free.md, nng_strfree.md
nng_strerror
NAME
nng_strerror — return an error description
SYNOPSIS
#include <nng/nng.h>
const char * nng_strerror(int err);
DESCRIPTION
The nng_strerror() returns the human-readable description of the
given error in err.
The returned error message is provided in US English, but in the future locale-specific strings may be presented instead.
note
The specific strings associated with specific error messages are subject to change. Therefore applications must not depend on the message, but may use them verbatim when supplying information to end-users, such as in diagnostic messages or log entries.
RETURN VALUES
This function returns the human-readable error message, terminated
by a NUL byte.
nng_strfree
NAME
nng_strfree — free memory
SYNOPSIS
#include <nng/nng.h>
void nng_strfree(char *str);
DESCRIPTION
The nng_strfree() function deallocates the string str.
This is equivalent to using nng_free() with
the length of str plus one (for the NUL terminating byte) as
the size.
important
This should only be used with strings that were allocated
by nng_strdup() or nng_alloc().
In all cases, the allocation size of the string must be the same
as strlen(__str__) + 1.
important
Consequently, if the a string created with
nng_strdup() is modified to be shorter, then
it is incorrect to call this function.
(The nng_free() function can be used instead in that
case, using the length of the original string plus one for the size.)
SEE ALSO
nng_alloc, nng_free, nng_strdup
nng_version
NAME
nng_version — report library version
SYNOPSIS
#include <nng/nng.h>
const char * nng_version(void);
DESCRIPTION
The nng_version() function returns a human readable version number
for NNG.
Additionally, compile time version information is available via some predefined macros:
NNG_MAJOR_VERSION: Major version number.NNG_MINOR_VERSION: Minor version number.NNG_PATCH_VERSION: Patch version number.
NNG is developed and released using Semantic Versioning 2.0, and the version numbers reported refer to both the API and the library itself. (The ABI – application binary interface – between the library and the application is controlled in a similar, but different manner depending upon the link options and how the library is built.)
RETURN VALUES
NUL-terminated string containing the library version number.
Threads and Synchronization
Threads
Mutexes
Condition Variables
nng_cv_alloc
NAME
nng_cv_alloc — allocate condition variable
SYNOPSIS
#include <nng/nng.h>
#include <nng/supplemental/util/platform.h>
typedef struct nng_cv nng_cv;
int nng_cv_alloc(nng_cv **cvp, nng_mtx *mtx);
DESCRIPTION
The nng_cv_alloc() function allocates a condition variable, using
the mutex mtx, and returns it in cvp.
Every condition variable is associated with a mutex, which must be
owned when a thread waits for the condition using
nng_cv_wait() or
nng_cv_until().
The mutex must also be owned when signaling the condition using the
nng_cv_wake() or
nng_cv_wake1() functions.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient free memory exists.
SEE ALSO
nng_cv_free, nng_cv_until, nng_cv_wait, nng_cv_wake, nng_cv_wake1, nng_mtx_alloc
nng_cv_free
NAME
nng_cv_free — free condition variable
SYNOPSIS
#include <nng/nng.h>
#include <nng/supplemental/util/platform.h>
void nng_cv_free(nng_cv *cv);
DESCRIPTION
The nng_cv_free() function frees the condition variable cv.
SEE ALSO
nng_cv_until()
NAME
nng_cv_until — wait for condition or timeout
SYNOPSIS
#include <nng/nng.h>
#include <nng/supplemental/util/platform.h>
int nng_cv_until(nng_cv *cv, nng_time when);
DESCRIPTION
The nng_cv_until() waits until either the condition variable cv is signaled
by another thread calling either
nng_cv_wake() or
nng_cv_wake1(), or the system clock (as tracked
by nng_clock()) reaches when.
The caller must have have ownership of the mutex that was used when cv was allocated. This function will drop the ownership of that mutex, and reacquire it atomically just before returning to the caller. (The waiting is done without holding the mutex.)
Spurious wakeups can occur.
tip
Any condition may be used or checked, but the condition must be checked, as it is possible for this function to wake up spuriously. The best way to do this is inside a loop that repeats until the condition tests for true.
EXAMPLE
The following example demonstrates use of this function:
Example 1: Waiting for the condition
expire = nng_clock() + 1000; // 1 second in the future
nng_mtx_lock(m); // assume cv was allocated using m
while (!condition_true) {
if (nng_cv_until(cv, expire) == NNG_ETIMEDOUT) {
printf("Time out reached!\n");
break;
}
}
// condition_true is true
nng_mtx_unlock(m);
Example 2: Signaling the condition
nng_mtx_lock(m);
condition_true = true;
nng_cv_wake(cv);
nng_mtx_unlock(m);
SEE ALSO
nng_clock(), nng_cv_alloc(), nng_cv_wait(), nng_cv_wake(), nng_cv_wake1(), nng_mtx_alloc(), nng_mtx_lock(), nng_mtx_unlock()
nng_cv_wait
NAME
nng_cv_wait — wait for condition
SYNOPSIS
#include <nng/nng.h>
#include <nng/supplemental/util/platform.h>
void nng_cv_wait(nng_cv *cv);
DESCRIPTION
The nng_cv_wait() waits for the condition variable cv to be signaled
by another thread calling either nng_cv_wake() or
nng_cv_wake1().
The caller must have have ownership of the mutex that was used when cv was allocated. This function will drop the ownership of that mutex, and reacquire it atomically just before returning to the caller. (The waiting is done without holding the mutex.)
Spurious wakeups are possible.
tip
Any condition may be used or checked, but the condition must be checked, as it is possible for this function to wake up spuriously. The best way to do this is inside a loop that repeats until the condition tests for true.
EXAMPLE
The following example demonstrates use of this function:
Example 1: Waiting for the condition
nng_mtx_lock(m); // assume cv was allocated using m
while (!condition_true) {
nng_cv_wait(cv);
}
// condition_true is true
nng_mtx_unlock(m);
Example 2: Signaling the condition
nng_mtx_lock(m);
condition_true = true;
nng_cv_wake(cv);
nng_mtx_unlock(m);
SEE ALSO
nng_cv_alloc, nng_cv_until, nng_cv_wake, nng_cv_wake1, nng_mtx_alloc, nng_mtx_lock, nng_mtx_unlock
nng_cv_wake
NAME
nng_cv_wake — wake all waiters
SYNOPSIS
#include <nng/nng.h>
#include <nng/supplemental/util/platform.h>
void nng_cv_wake(nng_cv *cv);
DESCRIPTION
The nng_cv_wake() wakes any threads waiting for the condition variable cv
to be signaled in the nng_cv_wait() or
nng_cv_until() functions.
The caller must have have ownership of the mutex that was used when cv was allocated.
The caller should already have set the condition that the waiters will check, while holding the mutex.
tip
This function wakes all threads, which is generally safer but can
lead to a performance problem when there are many waiters, as they are all
woken simultaneously and may contend for resources.
See nng_cv_wake1() for a solution to this problem.
SEE ALSO
nng_cv_alloc, nng_cv_until, nng_cv_wait, nng_cv_wake1, nng_mtx_alloc, nng_mtx_lock, nng_mtx_unlock
nng_cv_wake1
NAME
nng_cv_wake1 — wake one waiter
SYNOPSIS
#include <nng/nng.h>
#include <nng/supplemental/util/platform.h>
void nng_cv_wake1(nng_cv *cv);
DESCRIPTION
The nng_cv_wake1() wakes at most one thread waiting for the condition
variable cv
to be signaled in the nng_cv_wait() or
nng_cv_until() functions.
The caller must have have ownership of the mutex that was used when cv was allocated.
The caller should already have set the condition that the waiters will check, while holding the mutex.
note
The caller cannot predict which waiter will be woken, and so the design must
ensure that it is sufficient that any waiter be woken.
When in doubt, it is safer to use nng_cv_wake().
SEE ALSO
nng_cv_alloc, nng_cv_until, nng_cv_wait, nng_cv_wake, nng_mtx_alloc, nng_mtx_lock, nng_mtx_unlock
nng_mtx_alloc
NAME
nng_mtx_alloc — allocate mutex
SYNOPSIS
#include <nng/nng.h>
#include <nng/supplemental/util/platform.h>
typedef struct nng_mtx nng_mtx;
int nng_mtx_alloc(nng_mtx **mtxp);
DESCRIPTION
The nng_mtx_alloc() function allocates mutex and returns it in mtxp.
The mutex objects created by this function are suitable only for simple lock and unlock operations, and are not recursive. Every effort has been made to use light-weight underlying primitives when available.
Mutex (mutual exclusion) objects can be thought of as binary semaphores, where only a single thread of execution is permitted to acquire the semaphore.
Furthermore, a mutex can only be unlocked by the thread that locked it.
RETURN VALUES
This function returns 0 on success, and non-zero otherwise.
ERRORS
NNG_ENOMEM: Insufficient free memory exists.
SEE ALSO
nng_cv_alloc, nng_mtx_free, nng_mtx_lock, nng_mtx_unlock
nng_mtx_free
NAME
nng_mtx_free — free mutex
SYNOPSIS
#include <nng/nng.h>
#include <nng/supplemental/util/platform.h>
void nng_mtx_free(nng_mtx *mtx);
DESCRIPTION
The nng_mtx_free() function frees the mutex mtx.
The mutex must not be locked when this function is called.
SEE ALSO
nng_mtx_lock
NAME
nng_mtx_lock — lock mutex
SYNOPSIS
#include <nng/nng.h>
#include <nng/supplemental/util/platform.h>
void nng_mtx_lock(nng_mtx *mtx);
DESCRIPTION
The nng_mtx_lock() acquires exclusive ownership of the mutex mtx.
If the lock is already owned, this function will wait until the current
owner releases it with nng_mtx_unlock().
If multiple threads are waiting for the lock, the order of acquisition is not specified.
note
A mutex can only be unlocked by the thread that locked it.
note
Mutex locks are not recursive; attempts to reacquire the same mutex may result in deadlock or aborting the current program. It is a programming error for the owner of a mutex to attempt to reacquire it.
SEE ALSO
nng_cv_alloc, nng_mtx_alloc, nng_mtx_unlock
nng_mtx_unlock(3supp)
NAME
nng_mtx_unlock — unlock mutex
SYNOPSIS
#include <nng/nng.h>
#include <nng/supplemental/util/platform.h>
void nng_mtx_unlock(nng_mtx *mtx);
DESCRIPTION
The nng_mtx_unlock() relinquishes ownership of the mutex mtx that
was previously acquired via nng_mtx_lock().
note
A mutex can only be unlocked by the thread that locked it. Attempting to unlock a mutex that is not owned by the caller will result in undefined behavior.
SEE ALSO
Legacy Compatibility Functions
NNG provides source-level compatibility for most libnanomsg 1.0 applications.
This is intended to facilitate converting legacy applications to use NNG. New applications should use the newer NNG APIs instead.
Applications making use of this must take care to link with libnng instead of libnn.
tip
While not recommended for long term use, the value returned by
nng_socket_id() can be used with these functions
just like a value returned by nn_socket().
This can be way to facilitate incremental transition to the new API.
Some capabilities, protocols, and transports, will not be accessible using this API, as the compatible API has no provision for expression of certain concepts introduced in the new API.
While reasonable efforts have been made to provide for compatibility, some things may behave differently, and some less common parts of the libnanomsg 1.0 API are not supported at this time, including certain options and the statistics API. See the Caveats section below.
Availability
The availability of this legacy API depends on whether the library was configured to include it.
note
Future versions of NNG may not include this compatibility layer by default, or even at all. Modernizing applications to use the new API is strongly recommended.
Compiling
When compiling legacy nanomsg applications, it will generally be
necessary to change the include search path to add the compat subdirectory
of the directory where headers were installed.
For example, if NNG is installed in $prefix, then header files will
normally be located in $prefix/include/nng.
In this case, to build legacy nanomsg apps against NNG you would
add $prefix/include/nng/compat to your compiler’s search path.
Alternatively, you can change your source code so that #include statements
referring to <nanomsg> instead refer to <nng/compat/nanomsg>.
For example, instead of:
#include <nanomsg/nn.h>
#include <nanomsg/reqrep.h>
you would have this:
#include <nng/compat/nanomsg/nn.h>
#include <nng/compat/nanomsg/reqrep.h>
Legacy applications built using these methods should be linked against libnng instead of libnn, just like any other NNG application.
Caveats
The following caveats apply when using the legacy API with NNG.
-
Socket numbers can be quite large. The legacy libnanomsg attempted to reuse socket numbers, like file descriptors in UNIX systems. NNG avoids this to prevent accidental reuse or collision after a descriptor is closed. Consequently, socket numbers can become quite large, and should probably not be used for array indices.
-
The following options (
nn_getsockopt) are unsupported:NN_SNDPRIO,NN_RCVPRIO,NN_IPV4ONLY. -
Access to statistics using this legacy API
nn_get_statistic()is unsupported. -
Some transports can support longer URLs than legacy libnanomsg can. It is a good idea to use short pathnames in URLs if interoperability is a concern.
-
Only absolute paths are supported in
ipc://URLs. For example,ipc:///tmp/mysocketis acceptable, butipc://mysocketis not. -
The WebSocket transport in this implementation (
ws://URLs) only supportsBINARYframes. -
Some newer transports are unusable from this mode. In particular, this legacy API offers no way to configure TLS or ZeroTier parameters that may be required for use.
-
ABI versioning of the compatibility layer is not supported, and the
NN_VERSION_macros are not present. -
Runtime symbol information is not implemented. Specifically, there is no
nn_symbol()function. -
The TCP transport (
tcp://URLs) does not support specifying the local address or interface when binding. (This could be fixed in the future, but most likely this will be available only using the new API.) -
The values of
NN_RCVMAXSIZEare constrained. Specifically, values set larger than 2GB using the new API will be reported as unlimited (-1) in the new API, and the value0will disable any enforcement, just like-1. (There is no practical reason to ever want to limit the receive size to zero.) -
This implementation counts buffers in terms of messages rather than bytes. As a result, the buffer sizes accessed with
NN_SNDBUFandNN_RCVBUFare rounded up to a whole number of kilobytes, then divided by 1024, in order to approximate buffering assuming 1 KB messages. Few applications should need to adjust the default values.
Index
socket transport, 1
ABI, 1
abstract sockets, 1
AF_UNIX, 1, 2
application binary interface, 1
asynchronous I/O, 1, 2
back-pressure, 1, 2, 3
backtrace, 1, 2, 3, 4, 5
best-effort, 1, 2, 3
BUS protocol, 1
callback, 1, 2
compatibility layer, 1
concurrent, 1
condition variable, 1
context, 1, 2
cooked mode, 1
flow control, 1
forwarder, 1
half-duplex, 1
headroom, 1
horizontal scalability, 1
idempotent, 1
identifiers, 1
INADDR_ANY, 1
inproc transport, 1, 2
intra-process, 1
ipc transport, 1
IPv6, 1
leader election, 1
legacy applications, 1
load-balancing, 1, 2, 3
loop-back, 1
message, 1
body, 1, 2, 3, 4
header, 1, 2
mutex, 1
named pipes, 1
NNG_AF_UNSPEC, 1
NNG_CTX_INITIALIZER, 1
NNG_DURATION_DEFAULT, 1, 2
NNG_DURATION_INFINITE, 1, 2
NNG_ELIDE_DEPRECATED, 1, 2
NNG_FLAG_ALLOC, 1, 2
NNG_FLAG_NONBLOCK, 1, 2, 3, 4, 5, 6
NNG_MAJOR_VERSION, 1
NNG_MAP_RANDOM, 1
NNG_MINOR_VERSION, 1
NNG_OPT_SOCKET_FD, 1, 2
NNG_PATCH_VERSION, 1
NNG_SOCKET_INITIALIZER, 1
option, see Options
NNG_OPT_LOCADDR, 1
NNG_OPT_PEER_UID, 1
NNG_OPT_REQ_RESENDTICK, 1
NNG_OPT_REQ_RESENDTIME, 1
NNG_OPT_SUB_PREFNEW, 1
NNG_OPT_SUB_SUBSCRIBE, 1
NNG_OPT_SUB_UNSUBSCRIBE, 1
NNG_OPT_SURVEYOR_SURVEYTIME, 1
options, context, 1, 2
PAIR protocol, 1
pipeline pattern, 1, 2, 3
polyamorous mode, 1, 2
port number, 1
protocol, 1
BUS, 1, 2
PAIR, 1, 2
PUB, 1, 2
PULL, 1, 2
PUSH, 1, 2
REP, 1, 2
REQ, 1, 2
RESPONDENT, 1, 2
SUB, 1, 2
SURVEYOR, 1, 2
PUB protocol, 1
publisher, 1
PULL protocol, 1
PUSH protocol, 1
raw mode, 1, 2, 3
reflector, 1
REP protocol, 1
REQ protocol, 1
request/reply pattern, 1, 2, 3
RESPONDENT protocol, 1
scatter/gather, 1
service discovery, 1
socket://, 1
SUB protocol, 1
subscribe, 1
subscriber, 1
survey pattern, 1, 2
SURVEYOR protocol, 1
tailroom, 1
tcp transport, 1, 2
TCP/IP, 1, 2
time-to-live, 1
timeout, 1
transport, 1
inproc, 1
ipc, 1
tcp, 1
UNIX domain sockets, 1
URI, see URI
abstract://, 1
inproc://, 1
ipc://, 1
tcp://, 1
unix://, 1
version number, 1
voting, 1
zero-copy, 1