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 inAF_SPsockets, 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 callingnn_closeagain.
โญ 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_SOCKETlevel. - For socket-type-specific options, use the socket type as the
$levelargument (e.g.NN_SUB). - For transport-specific options, use the ID of the transport as the
$levelargument (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 afternn_closehas been called, in milliseconds. Negative values mean infinite linger ๐ณ The type of the option is int. The default value is1000(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 is128kB.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 is128kB.NN_SNDTIMEOโ The timeout for send operation on the socket, in milliseconds. If a message cannot be sent within the specified timeout, anEAGAINerror 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, anEAGAINerror 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 is100(0.1 second).NN_RECONNECT_IVL_MAXโ This one is to be used only in addition to theNN_RECONNECT_IVLoption. It specifies the maximum reconnection interval. On each reconnect attempt, the previous interval is doubled untilNN_RECONNECT_IVL_MAXis reached. A value of zero means no exponential backoff is performed and the reconnect interval is based only onNN_RECONNECT_IVL. IfNN_RECONNECT_IVL_MAXis less thanNN_RECONNECT_IVL, it is ignored. The type of the option is int. The default value is0.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 is1, the lowest priority is16. The default value is8.NN_IPV4ONLYโ If set to1, only IPv4 addresses are used. If set to0, both IPv4 and IPv6 addresses are used. The default value is1.
๐ฆ 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_SOCKETlevel. - For socket-type-specific options, use the socket type for the
$levelargument (e.g.NN_SUB). - For transport-specific options, use the ID of the transport as the
$levelargument (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$levelindicated.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 tonn_socket.NN_PROTOCOLโ Returns the protocol constant as it was passed tonn_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 isint. 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 isint. 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_bindandnn_connectcan 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_connectandnn_bindmay 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โ thehowparameter 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 callingnn_shutdownagain. 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 andnn_errnogets set toEAGAIN. 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" eraEAGAINโ 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 andnn_errnogets set toEAGAIN.
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 withnn_errnoset toEAGAIN.
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 andnn_errnogets set toEAGAIN. 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 anAF_SP_RAWsocket; 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 tonn_sendwill 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 isint. Default value is60000(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 isstring.NN_SUB_UNSUBSCRIBEโ defined on the full SUB socket. Unsubscribes you from a particular topic. Type of the option isstring. 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 theETIMEDOUTerror. 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 theETIMEDOUTerror and all subsequent responses to the survey get silently dropped. The deadline is measured in milliseconds. Option type isint. Default value is1000(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 to1, 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 isint. The default value is0.
โจ 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
- ubuntu stonking: libnanomsg-raw-perl 0.10-3build6 ยท MIT
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms