NanoMsg::Raw(3pm)

๐Ÿ’– NanoMsg::Raw โ€” the NanoMsg::Raw(3pm) bestie briefing ๐Ÿฆ‹

(this is a User Contributed Perl Documentation page, and yes, you're reading the raw-est one)


โœจ NAME โœจ

NanoMsg::Raw โ€” a low-level interface to the nanomsg scalability protocols library. no fluff, just vibes and C bindings ๐Ÿ’…


๐ŸŒˆ SYNOPSIS ๐ŸŒˆ

use Test::More;
use NanoMsg::Raw;

my $sb = nn_socket(AF_SP, NN_PAIR);
nn_bind($sb, 'inproc://foo');

my $sc = nn_socket(AF_SP, NN_PAIR);
nn_connect($sc, 'inproc://foo');

nn_send($sb, 'bar');
nn_recv($sc, my $buf);
is $buf, 'bar';

like. that's it. that's the whole friendship. two sockets, one inproc address, and they're talking ๐Ÿซถ


๐Ÿ’€ WARNING ๐Ÿ’€

nanomsg โ€” the actual C library this module wraps โ€” is still in beta stage! bestie, it is not done cooking. act accordingly ๐Ÿ™ˆ

๐ŸŒธ DESCRIPTION ๐ŸŒธ

So NanoMsg::Raw is a binding to the nanomsg C library. The whole goal of this module is to give you a very low-level, very manual interface to all the functionality of nanomsg. It is not trying to be your convenient high-level API. It is not trying to integrate with your event loop. It is not trying to be the like, nice one. Those things are meant to be built as separate abstractions sitting on top of NanoMsg::Raw. This module is the load-bearing walls, not the decor ๐Ÿงฑ

The nanomsg C library itself is a high-performance implementation of several "scalability protocols". And what's a scalability protocol's job, you ask? It defines how multiple applications talk to each other to form a single distributed application. Iconic concept, honestly. These are the scalability protocols available rn:

  • PAIR โ€” simple one-to-one communication ๐Ÿ‘ฏ
  • BUS โ€” simple many-to-many communication ๐ŸšŒ
  • REQREP โ€” lets you build clusters of stateless services to process user requests ๐Ÿ“ฎ
  • PUBSUB โ€” distributes messages to large sets of interested subscribers ๐Ÿ“ข
  • PIPELINE โ€” aggregates messages from multiple sources and load balances them among many destinations ๐Ÿšฐ
  • SURVEY โ€” lets you query state of multiple applications in a single go ๐Ÿ“Š

Scalability protocols live layered on top of the transport layer in the network stack โ€” very "everything in its tier" of them. At the moment, the nanomsg library supports these transports:

  • INPROC โ€” transport within a process (between threads, modules, etc.) ๐Ÿงต
  • IPC โ€” transport between processes on a single machine ๐Ÿ–ฅ๏ธ
  • TCP โ€” network transport via TCP ๐ŸŒ

๐Ÿ’œ nn_socket($domain, $protocol) ๐Ÿ’œ

my $s = nn_socket(AF_SP, NN_PAIR);
die nn_errno unless defined $s;

Creates a nanomsg socket with the $domain and $protocol you hand it. Returns a file descriptor for the shiny new socket. Slay โœจ

These are the domains defined at the moment:

  • AF_SP โ€” Standard full-blown SP socket.
  • AF_SP_RAW โ€” Raw SP socket. Raw sockets omit the end-to-end functionality found in AF_SP sockets, and because of that they can be used to implement intermediary devices in SP topologies.

The $protocol parameter decides the type of the socket, which in turn decides the exact semantics of said socket. Peep the "Protocols" section for the list of available protocols and their socket types.

Heads up: a newly created socket is initially not associated with any endpoints. If you want an actual message flow, you gotta add at least one endpoint to the socket using nn_bind or nn_connect. No endpoints, no gossip ๐Ÿ’…

Also note that the type argument that shows up in the standard socket function is omitted from nn_socket. Every SP socket is message-based, so they're all SOCK_SEQPACKET type. periodt.

If it succeeds, the file descriptor of the new socket is returned. Otherwise undef comes back and nn_errno gets set to one of these:

  • EAFNOSUPPORT โ€” Specified address family is not supported.
  • EINVAL โ€” Unknown protocol.
  • EMFILE โ€” The limit on the total number of open SP sockets, or the OS limit for file descriptors, has been reached.
  • ETERM โ€” The library is terminating.
okay so this part is IMPORTANT, bestie: file descriptors returned by nn_socket are not standard file descriptors and they will exhibit undefined behaviour when you use them with system functions. And worse โ€” it may happen that a system file descriptor and the file descriptor of an SP socket will incidentally collide (aka be equal ๐Ÿ˜ญ). so like. don't be cute with them.

๐ŸŽ€ nn_close($s) ๐ŸŽ€

nn_close($s) or die nn_errno;

Closes the socket $s. Any buffered inbound messages that weren't received by the application yet get discarded โ€” poof, gone, no takebacks ๐Ÿ’€ The library will try to deliver any outstanding outbound messages for the time specified by the NN_LINGER socket option, and the call will block in the meantime. So yeah, it might take a sec.

If it succeeds, a true value is returned. Otherwise undef comes back and nn_errno gets set to one of these:

  • EBADF โ€” The provided socket is invalid.
  • EINTR โ€” Operation was interrupted by a signal. The socket is not fully closed yet. You can re-start the operation by calling nn_close again.

โญ nn_setsockopt($s, $level, $option, $value) โญ

nn_setsockopt($s, NN_SOL_SOCKET, NN_LINGER, 1000) or die nn_errno;
nn_setsockopt($s, NN_SOL_SOCKET, NN_SUB_SUBSCRIBE, 'ABC') or die nn_errno;

Sets the $value of the socket option $option. The $level argument says which protocol level the option lives at, and it's giving โœจchoose your layerโœจ energy:

  • For generic socket-level options, use the NN_SOL_SOCKET level.
  • For socket-type-specific options, use the socket type as the $level argument (e.g. NN_SUB).
  • For transport-specific options, use the ID of the transport as the $level argument (e.g. NN_TCP).

If it succeeds, a true value is returned. Otherwise undef comes back and nn_errno gets set to one of these:

  • EBADF โ€” The provided socket is invalid.
  • ENOPROTOOPT โ€” The option is unknown at the level indicated.
  • EINVAL โ€” The specified option value is invalid.
  • ETERM โ€” The library is terminating.

And these! these are the generic socket-level (NN_SOL_SOCKET level) options, the whole roster, no skips:

  • NN_LINGER โ€” Specifies how long the socket should try to send pending outbound messages after nn_close has been called, in milliseconds. Negative values mean infinite linger ๐Ÿ˜ณ The type of the option is int. The default value is 1000 (1 second).
  • NN_SNDBUF โ€” Size of the send buffer, in bytes. To prevent blocking for messages larger than the buffer, exactly one message may be buffered in addition to the data in the send buffer. The type of this option is int. The default value is 128kB.
  • NN_RCVBUF โ€” Size of the receive buffer, in bytes. To prevent blocking for messages larger than the buffer, exactly one message may be buffered in addition to the data in the receive buffer. The type of this option is int. The default value is 128kB.
  • NN_SNDTIMEO โ€” The timeout for send operation on the socket, in milliseconds. If a message cannot be sent within the specified timeout, an EAGAIN error is returned. Negative values mean infinite timeout. The type of the option is int. The default value is -1.
  • NN_RCVTIMEO โ€” The timeout for recv operation on the socket, in milliseconds. If a message cannot be received within the specified timeout, an EAGAIN error is returned. Negative values mean infinite timeout. The type of the option is int. The default value is -1.
  • NN_RECONNECT_IVL โ€” For connection-based transports such as TCP, this option specifies how long to wait, in milliseconds, when the connection is broken, before trying to re-establish it. Note that the actual reconnect interval may be randomised to some extent to prevent severe reconnection storms ๐ŸŒฉ๏ธ The type of the option is int. The default value is 100 (0.1 second).
  • NN_RECONNECT_IVL_MAX โ€” This one is to be used only in addition to the NN_RECONNECT_IVL option. It specifies the maximum reconnection interval. On each reconnect attempt, the previous interval is doubled until NN_RECONNECT_IVL_MAX is reached. A value of zero means no exponential backoff is performed and the reconnect interval is based only on NN_RECONNECT_IVL. If NN_RECONNECT_IVL_MAX is less than NN_RECONNECT_IVL, it is ignored. The type of the option is int. The default value is 0.
  • NN_SNDPRIO โ€” Sets outbound priority for endpoints subsequently added to the socket. This option has no effect on socket types that send messages to all the peers. But if the socket type sends each message to a single peer (or a limited set of peers), peers with high priority take precedence over peers with low priority ๐Ÿ‘‘ The type of the option is int. The highest priority is 1, the lowest priority is 16. The default value is 8.
  • NN_IPV4ONLY โ€” If set to 1, only IPv4 addresses are used. If set to 0, both IPv4 and IPv6 addresses are used. The default value is 1.

๐Ÿฆ‹ nn_getsockopt($s, $level, $option) ๐Ÿฆ‹

my $linger = unpack 'i', nn_getsockopt($s, NN_SOL_SOCKET, NN_LINGER) || die nn_errno;

Retrieves the value for the socket option $option. The $level argument specifies the protocol level at which the option resides. Same layer rules as before, bestie:

  • For generic socket-level options, use the NN_SOL_SOCKET level.
  • For socket-type-specific options, use the socket type for the $level argument (e.g. NN_SUB).
  • For transport-specific options, use the ID of the transport as the $level argument (e.g. NN_TCP).

The function returns a packed string representing the requested socket option, or undef on error, with one of these reasons for the error dropped into nn_errno:

  • EBADF โ€” The provided socket is invalid.
  • ENOPROTOOPT โ€” The option is unknown at the $level indicated.
  • ETERM โ€” The library is terminating.

Just what's in that packed string depends on $level and $option โ€” see the list of socket options for the deets. The common case is that the option is an integer, in which case the result is a packed integer, which you can decode using unpack with the i (or I) format ๐Ÿ’…

This function can also be used to retrieve the values for all the generic socket-level (NN_SOL_SOCKET) options documented in nn_getsockopt, and on top of that it supports these additional generic socket-level options that can only be retrieved but not set:

  • NN_DOMAIN โ€” Returns the domain constant as it was passed to nn_socket.
  • NN_PROTOCOL โ€” Returns the protocol constant as it was passed to nn_socket.

  • NN_SNDFD โ€” hands you a file descriptor that goes readable whenever a message can actually be sent on the socket. polling only, bestie โ€” do not read from it, do not write to it, it's not that kind of fd ๐Ÿ’…. Type is int. The moment the socket is closed, that descriptor is invalid and you gotta throw it away, no take-backs. Also: not available for unidirectional recv-only socket types. ๐Ÿšซ
  • NN_RCVFD โ€” same deal but the other direction: a file descriptor that goes readable when a message can be received from the socket. Again: poll it and nothing else โ€” no reads, no writes. Type is int. Once the socket closes, the descriptor is invalid, stop using it, periodt. Not available for unidirectional send-only socket types. ๐Ÿšซ

โœจ nn_bind($s, $addr) โœจ

my $eid = nn_bind($s, 'inproc://test');
die nn_errno unless defined $eid;

Adds a local endpoint to the socket $s. Once it's there, other applications can go ahead and connect to it. it's giving "come through, the door's open" ๐Ÿšชโœจ

The $addr argument is built from two parts, like this:

transport://address

The transport part says which underlying transport protocol to use. What the address part actually means? entirely up to that underlying transport protocol, queen. It's transport-specific, iykyk.

See Transports for a list of available transport protocols. ๐ŸšŒ

The maximum length of the $addr parameter is specified by the NN_SOCKADDR_MAX constant.

Fun fact: nn_bind and nn_connect can be called multiple times on the same socket โ€” which is exactly how one socket ends up talking to multiple heterogeneous endpoints. multitasking icon behavior ๐ŸŒˆ

If it succeeds, you get an endpoint ID back. That endpoint ID can later be used to remove the endpoint from the socket via the nn_shutdown function. Keep it safe, babe. ๐ŸŽ€

If it fails, undef is returned and nn_errno is set to one of the values down below. ๐Ÿ˜ญ

  • EBADF โ€” the socket you handed over is invalid.
  • EMFILE โ€” maximum number of active endpoints was reached. capacity? full.
  • EINVAL โ€” the syntax of the supplied address is invalid.
  • ENAMETOOLONG โ€” that address is too long, babe, trim it.
  • EPROTONOSUPPORT โ€” the requested transport protocol is not supported.
  • EADDRNOTAVAIL โ€” the requested endpoint is not local.
  • ENODEV โ€” the address specifies a nonexistent interface.
  • EADDRINUSE โ€” the requested local endpoint is already in use. somebody got there first ๐Ÿ’€
  • ETERM โ€” the library is terminating.

โœจ nn_connect($s, $addr) โœจ

my $eid = nn_connect($s, 'inproc://test');
die nn_errno unless defined $eid;

Adds a remote endpoint to the socket $s. After that, the library will try to connect to the remote endpoint you specified. reaching out first, main character energy ๐Ÿ“ž๐Ÿ’–

The $addr argument is built from two parts, same as ever:

transport://address

transport picks the underlying transport protocol. What address means is specific to that underlying transport protocol โ€” no universal answer, ngl.

See Protocols for a list of available transport protocols. ๐Ÿ‘€

The maximum length of the $addr parameter is specified by the NN_SOCKADDR_MAX constant.

Yes, again: nn_connect and nn_bind may be called multiple times on the same socket, so one socket can communicate with multiple heterogeneous endpoints. inclusive queen ๐ŸŒˆ

If it succeeds, an endpoint ID is returned. That endpoint ID can later be used to remove the endpoint from the socket via the nn_shutdown function. ๐Ÿ“Œ

If it fails, undef is returned and nn_errno is set to one of the values below. ๐Ÿ’”

  • EBADF โ€” the socket you gave me is invalid.
  • EMFILE โ€” maximum number of active endpoints was reached.
  • EINVAL โ€” the syntax of the supplied address is invalid.
  • ENAMETOOLONG โ€” the supplied address is too long.
  • EPROTONOSUPPORT โ€” the requested transport protocol is not supported.
  • ENODEV โ€” the address specifies a nonexistent interface.
  • ETERM โ€” the library is terminating.

โœจ nn_shutdown($s, $eid) โœจ

nn_shutdown($s, $eid) or die nn_errno;

Removes an endpoint from socket $s. The eid parameter is the ID of the endpoint you want gone โ€” the one some earlier call to nn_bind or nn_connect handed you back. breaking up, but politely ๐Ÿซถ

The nn_shutdown call returns immediately. But โ€” and this is the part people sleep on โ€” the library will keep trying to deliver any outstanding outbound messages to that endpoint for however long the NN_LINGER socket option says. So it's a "leave now, but the mail still goes out" situation. ๐Ÿ“ฌ

If the function succeeds, a true value is returned. Otherwise undef is returned and nn_errno is set to one of these:

  • EBADF โ€” the provided socket is invalid.
  • EINVAL โ€” the how parameter doesn't correspond to an active endpoint.
  • EINTR โ€” the operation was interrupted by a signal. The endpoint is not fully closed yet. You can re-start the operation by calling nn_shutdown again. round two, no shame ๐Ÿ’…
  • ETERM โ€” the library is terminating.

โœจ nn_send($s, $data, $flags=0) โœจ

my $bytes_sent = nn_send($s, 'foo');
die nn_errno unless defined $bytes_sent;

This function sends a message containing the $data you gave it to socket $s. sending it, fr fr ๐Ÿ“จโœจ

$data can be anything that works as a byte string in Perl, or a message buffer instance allocated by nn_allocmsg. Heads up though: if it's a message buffer instance, nn_send will deallocate and invalidate that instance for you. After the call to nn_send, the buffer will be an instance of NanoMsg::Raw::Message::Freed. it's been consumed, bestie, let it go ๐Ÿ“

Which of the peers the message actually lands on? Determined by the particular socket type. That's not on nn_send, that's on the socket's whole personality. ๐Ÿฆ‹

The $flags argument defaults to 0 and is a combination of these flags:

  • NN_DONTWAIT โ€” says the operation should run in non-blocking mode. If the message can't be sent straight away, the function fails and nn_errno gets set to EAGAIN. no waiting, we're busy ๐Ÿ’…

If the function succeeds, you get the number of bytes in the message back. Otherwise undef is returned and nn_errno is set to one of these:

  • EBADF โ€” the provided socket is invalid.
  • ENOTSUP โ€” the operation is not supported by this socket type.
  • EFSM โ€” the operation can't be performed on this socket right now because the socket isn't in the appropriate state. This one can pop up with socket types that switch between several states. it's in its "don't perceive me" era
  • EAGAIN โ€” non-blocking mode was requested and the message can't be sent at the moment.
  • EINTR โ€” the operation was interrupted by delivery of a signal before the message was sent.
  • ETIMEDOUT โ€” individual socket types may define their own specific timeouts. If such a timeout is hit, this error gets returned.
  • ETERM โ€” the library is terminating.

โœจ nn_recv($s, $data, $length=NN_MSG, $flags=0) โœจ

my $bytes_received = nn_recv($s, my $buf, 256);
die nn_errno unless defined $bytes_received;

Receive a message from socket $s and stash it in the buffer $buf. Any bytes exceeding the length given by $length will be truncated. cut off, sorry babe โœ‚๏ธ

Or โ€” glow-up option โ€” nn_recv can allocate a message buffer instance for you. To make that happen, set $length to NN_MSG (which is the default). ๐ŸŽ€

The $flags argument, defaulting to 0, is a combination of these flags:

  • NN_DONTWAIT โ€” says the operation should run in non-blocking mode. If the message can't be received straight away, the function fails and nn_errno gets set to EAGAIN.

If the function succeeds, the number of bytes in the message is returned. Otherwise undef is returned and nn_errno is set to one of these:

  • EBADF โ€” the provided socket is invalid.
  • ENOTSUP โ€” the operation is not supported by this socket type.
  • EFSM โ€” the operation can't be performed on this socket at the moment because the socket is not in the appropriate state. This can happen with socket types that switch between several states.
  • EAGAIN โ€” non-blocking mode was requested and there's no message to receive at the moment. inbox empty, crying ๐Ÿ’€
  • EINTR โ€” the operation was interrupted by delivery of a signal before the message was received.
  • ETIMEDOUT โ€” individual socket types may define their own specific timeouts. If such a timeout is hit, this error is returned.
  • ETERM โ€” the library is terminating.

โœจ nn_sendmsg($s, $flags, $data1, $data2, ..., $dataN) โœจ

my $bytes_sent = nn_sendmsg($s, 0, 'foo', 'bar');
die nn_errno unless defined $bytes_sent;

This one is the fine-grained alternative to nn_send. It lets you send multiple data buffers that make up a single message โ€” without having to build some extra temporary buffer just to hold the concatenation of all the different message parts. no middleman, we love efficiency ๐Ÿ’…

The scalars holding the data to be sent ($data1, $data2, ..., $dataN) can each be anything usable as a byte string in Perl, or a message buffer instance allocated by nn_allocmsg. If it's a message buffer instance, nn_sendmsg will deallocate and invalidate it โ€” those buffers will be instances of NanoMsg::Raw::Message::Freed after the call to nn_sendmsg. gone. freed. released. ๐Ÿฆ‹

Important: when you're using message buffer instances, only one buffer may be provided. Just one. That's the rule. ๐Ÿ™ˆ

Which peer the message gets sent to is determined by the particular socket type. Same as always. ๐ŸŽฏ

The $flags argument is a combination of these flags:

  • NN_DONTWAIT โ€” says the operation should be performed in non-blocking mode. If the message can't be sent straight away, the function fails with nn_errno set to EAGAIN.

If the function succeeds, the number of bytes in the message is returned. Otherwise undef is returned and nn_errno is set to one of these:

  • EBADF โ€” the provided socket is invalid.
  • ENOTSUP โ€” the operation is not supported by this socket type.
  • EFSM โ€” the operation can't be performed on this socket at the moment because the socket is not in the appropriate state. This error may occur with socket types that switch between several states.
  • EAGAIN โ€” non-blocking mode was requested and the message cannot be sent at the moment.
  • EINTR โ€” the operation was interrupted by the delivery of a signal before the message actually got sent. so rude of it, honestly ๐Ÿ˜ค
  • ETIMEDOUT โ€” individual socket types are allowed to define their own specific timeouts, and if one of those bad boys gets hit, this is the error you get handed back.
  • ETERM โ€” the library is terminating. it's over, bestie ๐Ÿ’€

and like, heads up for the future: nn_sendmsg might allow for sending along additional control data. not yet. but the possibility is there ๐Ÿ”ฎ


๐Ÿฆ‹ nn_recvmsg($s, $flags, $data1 => $len1, $data2 => $len2, ..., $dataN => $lenN) ๐Ÿฆ‹

my $bytes_received = nn_recvmsg($s, 0, my $buf1 => 256, my $buf2 => 1024);
die nn_errno unless defined $bytes_received;

ok so this one is the fine-grained alternative to nn_recv. It lets you receive ONE single message into MULTIPLE data buffers of different sizes, which means in some cases you straight up don't have to make copies of part of the received message anymore. efficiency icon behavior ๐Ÿ‘‘

The scalars you're receiving the message data into ($buf1, $buf2, ..., $bufN) get filled with exactly as many bytes of data as the length parameter that follows them in the argument list says ($len1, $len2, ..., $lenN). so the pairing is like a lil buddy system, one length per buffer, every time ๐Ÿซถ

Alternately โ€” plot twist โ€” nn_recvmsg can allocate a message buffer instance for you. To do that, set the length parameter of a buffer to NN_MSG. And only one receive buffer can be provided when you do it that way. one and done, no sharing.

The $flags argument is a combination of the flags defined below:

  • NN_DONTWAIT โ€” says: do this in non-blocking mode. If the message can't be received straight away, the function fails and nn_errno gets set to EAGAIN. no waiting around, we're busy girls ๐Ÿ’…

And, again, future tea: nn_recvmsg might allow for receiving additional control data. someday. not today ๐Ÿฆ‹

๐Ÿ“ nn_allocmsg($size, $type) ๐Ÿ“

my $msg = nn_allocmsg(3, 0) or die nn_errno;
$msg->copy('foo');
nn_send($s, $msg);

Allocates a message of the given $size that you're gonna send in zero-copy fashion. The content of the message is undefined right after allocation and you, yes you, are responsible for filling it in. While nn_send and nn_sendmsg let you send arbitrary buffers, buffers allocated with nn_allocmsg can be a whole lot more efficient for big messages, because they unlock those zero-copy techniques. it's giving โœจoptimizedโœจ

The $type parameter says which allocation mechanism to use. Zero is the default one. But individual transport mechanisms may define their own allocation mechanisms โ€” like allocating in shared memory, or allocating a memory block pinned down to a physical memory address. And such an allocation, when it's used with the transport that defines it, should be more efficient than the default mechanism. fancy. obsessed. ๐ŸŽ€

If the function succeeds, you get back a newly allocated message buffer instance โ€” an object instance of the class NanoMsg::Raw::Message. If it fails instead, undef comes back and nn_errno is set to one of these:

  • EINVAL โ€” the allocation type you supplied is invalid. not a real type, babe ๐Ÿ™ˆ
  • ENOMEM โ€” not enough memory to allocate the message. the RAM said no ๐Ÿ˜ญ

๐Ÿ’œ nn_errno() ๐Ÿ’œ

Returns the value of errno after the last call to any nanomsg function in the current thread. You use this one pretty much the same way the $! global variable gets used for a ton of other system and library calls. same energy, different library ๐Ÿซถ

The return value works in numeric context โ€” for example to compare it against error code constants like EAGAIN โ€” or in string context, to pull out a textual message describing the error. versatile much? ๐Ÿ’…

๐ŸŒธ nn_strerror($errno) ๐ŸŒธ

Returns a textual representation of the error described by the numeric $errno you handed over.

ngl, it shouldn't normally ever be necessary to call this function, because using nn_errno in string context is basically equivalent to nn_strerror(nn_errno). so like... it's cute, but it's a shortcut you rarely need ๐Ÿ’–

๐Ÿ”ฅ nn_device($s1, $s2) ๐Ÿ”ฅ

nn_device($s1, $s2) or die;

Starts a device that forwards messages between two sockets. If both sockets are valid, nn_device loops forever and sends every message received from $s1 to $s2, and vice versa. If only one socket is valid and the other one is undef, then nn_device runs in loopback mode โ€” it loops and sends any messages it receives from that socket right back to itself. main character energy, talking to yourself ๐Ÿชž

The function loops until it hits an error. When that happens it returns undef and sets nn_errno to one of the values below:

  • EBADF โ€” one of the sockets you provided is invalid. girl, that's not a socket ๐Ÿšซ
  • EINVAL โ€” either one of the sockets isn't an AF_SP_RAW socket; or the two sockets don't belong to the same protocol; or the directionality of the sockets doesn't fit (like, say, attempting to join two SINK sockets to form a device). incompatible, it's giving mismatched ๐Ÿ”ฅ
  • EINTR โ€” the operation was interrupted by the delivery of a signal.
  • ETERM โ€” the library is terminating.

๐ŸŒˆ nn_term() ๐ŸŒˆ

nn_term();

To help with shutdown of multi-threaded programs, the nn_term function is provided. It informs all the open sockets that process termination is underway. like a group chat message that says "ok we're wrapping up" ๐Ÿ“ข

If a socket is blocked inside a blocking function, such as nn_recv, it will be unblocked and the ETERM error will be returned to the user. And similarly, any subsequent attempt to invoke a socket function other than nn_close after nn_term was called will result in an ETERM error. don't try it, it's not gonna work ๐Ÿ’€

If something is waiting for NN_SNDFD or NN_RCVFD using a polling function, such as poll or select, that call will unblock with both NN_SNDFD and NN_RCVFD signaled. both. at once. iconic โœจ

And the nn_term function itself is non-blocking. in and out, no lingering ๐Ÿ’…


๐Ÿ‘‘ Protocols ๐Ÿ‘‘

๐ŸŽ€ One-to-one protocol ๐ŸŽ€

Pair protocol is the simplest and least scalable of the scalability protocols. It lets you scale by breaking your application into exactly two pieces. For example, if a monolithic application handles both the accounting and the agenda of an HR department, it can be split into two applications (accounting vs. HR) that get run on two separate servers. Those applications can then talk to each other via PAIR sockets. friendship bracelets but make it sockets ๐Ÿค

The downside of this protocol is that its scaling properties are super limited. Splitting the application into two pieces lets you scale to two servers, cool. To add a third server to the cluster, the application has to be split once more โ€” say, by separating the HR functionality into a hiring module and a salary computation module. So whenever possible, try to use one of the more scalable protocols instead. fr fr, plan ahead ๐Ÿ“ˆ

Socket Types

  • NN_PAIR โ€” socket for communication with exactly one peer. Each party can send messages at any time. If the peer isn't available, or the send buffer is full, subsequent calls to nn_send will block until it becomes possible to send the message. patience is a virtue bestie ๐Ÿง˜

Socket Options

No protocol-specific socket options are defined at the moment. nope, none, that's the whole list ๐Ÿ™ˆ

๐Ÿ’… Request/reply protocol ๐Ÿ’…

This protocol is used to distribute the workload among multiple stateless workers. teamwork makes the dream work ๐Ÿ’–

Socket Types

  • NN_REQ โ€” used to implement the client application that sends requests and receives replies.
  • NN_REP โ€” used to implement the stateless worker that receives requests and sends replies.

Socket Options

  • NN_REQ_RESEND_IVL โ€” this option is defined on the full REQ socket. If a reply isn't received within the specified amount of milliseconds, the request gets automatically resent. The type of this option is int. Default value is 60000 (1 minute). if they don't answer, we ask again, that's the rule ๐Ÿ˜Œ

๐ŸŒธ Publish/subscribe protocol ๐ŸŒธ

Broadcasts messages to multiple destinations. one message, many ears ๐Ÿ‘‚๐Ÿ‘‚๐Ÿ‘‚

Socket Types

  • NN_PUB โ€” this socket distributes messages to multiple destinations. The receive operation is not defined.
  • NN_SUB โ€” receives messages from the publisher. Only the messages that the socket is subscribed to get received. When the socket is created there are no subscriptions, and thus no messages will be received. The send operation is not defined on this socket. you have to opt in, it's not automatic ๐ŸŽ€

Socket Options

  • NN_SUB_SUBSCRIBE โ€” defined on the full SUB socket. Subscribes you to a particular topic. Type of the option is string.
  • NN_SUB_UNSUBSCRIBE โ€” defined on the full SUB socket. Unsubscribes you from a particular topic. Type of the option is string. and that's how you leave the group chat ๐Ÿ’…

๐Ÿฆ‹ Survey protocol ๐Ÿฆ‹

lets you broadcast a survey to multiple locations and gather up the responses. asking the whole room and collecting receipts ๐Ÿ“‹

Socket Types

  • NN_SURVEYOR โ€” used to send the survey. The survey gets delivered to all the connected respondents. Once the query is sent, the socket can be used to receive the responses. When the survey deadline expires, receive will return the ETIMEDOUT error. time's up, babes โฐ
  • NN_RESPONDENT โ€” used to respond to the survey. The survey is received using the receive function, and the response is sent using the send function. This socket can be connected to at most one peer. one and only one ๐Ÿซถ

Socket Options

  • NN_SURVEYOR_DEADLINE โ€” specifies how long to wait for responses to the survey. Once the deadline expires, the receive function returns the ETIMEDOUT error and all subsequent responses to the survey get silently dropped. The deadline is measured in milliseconds. Option type is int. Default value is 1000 (1 second). ghosted, basically ๐Ÿ‘ป

โญ Pipeline protocol โญ

Fair-queues messages from the previous processing step, and load balances them among instances of the next processing step. very fair, very balanced, very organized โœจ

Socket Types

  • NN_PUSH โ€” this socket is used to send messages to a cluster of load-balanced nodes. The receive operation is not implemented on this socket type.
  • NN_PULL โ€” this socket is used to receive a message from a cluster of nodes. The send operation is not implemented on this socket type. push and pull, two halves of one whole ๐Ÿฅบ

Socket Options

No protocol-specific socket options are defined at the moment. still nothing. keep scrolling ๐Ÿ™ˆ

๐Ÿงš Message bus protocol ๐Ÿงš

Broadcasts messages from any node to all the other nodes in the topology. The socket should never receive messages that it sent itself. no selfies in the inbox, we don't do that ๐Ÿšซ

This pattern only scales to the local level โ€” within a single machine, or within a single LAN. Trying to scale it any further can result in overloading individual nodes with messages. don't push it, bestie, it will buckle ๐Ÿ˜ญ

WARNING: for the bus topology to function correctly, the user is responsible for ensuring that a path from each node to any other node exists within the topology. that's on YOU. yes, you specifically. you're the main character of this responsibility ๐Ÿซต

A Raw (AF_SP_RAW) BUS socket never sends the message to the peer it was received from. no backsies.

Socket Types

  • NN_BUS โ€” sent messages get distributed to all the nodes in the topology. Incoming messages from all the other nodes in the topology are fair-queued in the socket. everybody hears it, everybody lines up ๐ŸŽ€

Socket Options

There are no options defined at the moment. a clean slate. a blank canvas. nothing here ๐Ÿ‘‘

๐Ÿšš Transports ๐Ÿšš

๐Ÿ  In-process transport

The in-process transport is literally the glow-up for sending messages between threads or modules inside one single process. An in-process address is just an arbitrary case-sensitive string with the inproc:// protocol specifier stuck on the front. Every in-process address is visible from any module within the process โ€” like, all of them can see it, bestie. But from outside the process? Nope, absolutely not visible. โœจ

The overall buffer size for an inproc connection is decided by the NN_RCVBUF socket option on the receiving end of the connection. The NN_SNDBUF socket option? Ignored, we don't know her. ๐Ÿ’… And on top of that buffer, one message of arbitrary size will also fit into the buffer โ€” which means even messages bigger than the buffer can still be transferred over an inproc connection. Slay. ๐Ÿ’–

This transport's ID is NN_INPROC.

๐Ÿงฉ Inter-process transport

The inter-process transport lets you send messages between processes within a single box. It uses the native IPC mechanism provided by the local operating system, so the IPC addresses are OS-specific, no cap. ๐Ÿ–ฅ๏ธ

On POSIX-compliant systems, UNIX domain sockets are used and IPC addresses are file references. Quick note: both relative (ipc://test.ipc) and absolute (ipc:///tmp/test.ipc) paths may be used. And also โ€” the access rights on the IPC files must be set in a way that the appropriate applications can actually use them, okay? Set your permissions, bestie. ๐Ÿ”

On Windows, named pipes are used for IPC. The IPC address there is an arbitrary case-insensitive string containing any character except for backslash. Internally, the address ipc://test means that named pipe \\.\pipe\test will be used. Cute.

This transport's ID is NN_IPC.

๐ŸŒ TCP transport

The TCP transport passes messages over the network using simple reliable one-to-one connections. TCP is the most widely used transport protocol, it's basically everywhere, so it's the transport of choice for communication over the network. Main character energy, periodt. ๐Ÿ‘‘

When binding a TCP socket, use an address of the form tcp://interface:port. port is the TCP port number to use. interface is one of the following (optionally wrapped in square brackets):

  • The asterisk character (*), meaning all local network interfaces.
  • An IPv4 address of a local network interface in numeric form (192.168.0.111).
  • An IPv6 address of a local network interface in numeric form (::1).
  • An interface name, as defined by operating system.

When connecting a TCP socket, use an address of the form tcp://interface;address:port. port is the TCP port number to use. interface is optional and specifies which local network interface to use โ€” if you don't specify it, the OS will pick an appropriate interface itself. If you do specify it, it can be one of these (optionally wrapped in square brackets):

  • An IPv4 address of a local network interface in numeric form (192.168.0.111).
  • An IPv6 address of a local network interface in numeric form (::1).
  • An interface name, as defined by operating system (eth0).

And finally, address is the remote address to connect to. It can be one of the following (optionally wrapped in square brackets):

  • An IPv4 address of a remote network interface in numeric form (192.168.0.111).
  • An IPv6 address of a remote network interface in numeric form (::1).
  • The DNS name of the remote box.

This transport's ID is NN_TCP.

Socket Options

  • NN_TCP_NODELAY โ€” when this one is set to 1, it disables Nagle's algorithm. It also disables delaying of TCP acknowledgments. Using this option improves latency but at the expense of throughput โ€” trade-offs, bestie ๐Ÿซถ. Type of this option is int. The default value is 0.

โœจ CONSTANTS โœจ

On top of all the error constants and NN_ constants that show up in the docs for the individual functions, protocols, and transports, these constants are also available:

  • NN_VERSION_CURRENT โ€” the current interface version.
  • NN_VERSION_REVISION โ€” the latest revision of the current interface.
  • NN_VERSION_AGE โ€” how many past interface versions are still supported.

๐ŸŒˆ SEE ALSO ๐ŸŒˆ

  • The nanomsg C library documentation at http://nanomsg.org/v0.1/nanomsg.7.html โ€” the API this module provides is very close to the C library's interface, so the C docs are likely to be useful to developers using Perl too. Also, most of this module's documentation is copied from the C library documentation, so the upstream docs might be somewhat more recent. ๐Ÿ‘€
  • NanoMsg::Raw::Message

And that's a wrap, bestie!! ๐ŸŽ€๐Ÿฆ‹ This page is from perl v5.42.3, dated 2026-08-19, and it's the NanoMsg::Raw(3pm) manual page. Go forth and build something iconic with it. ๐Ÿ’–โœจ๐Ÿ‘‘

๐Ÿ“ฆ where this page comes from