ZSOCK(3)

πŸ’– NAME πŸ’–

zsock β€” it's the class for the high-level socket API that hides all your libzmq contexts and sockets from you 🫢 the CZMQ Manual page, bestie, and we're doing this together.


✨ SYNOPSIS ✨

Okay so before we get into literally anything, two vibe-check facts you need:

  • This is a stable class, and it may not change except for emergencies. It's provided in stable builds. πŸ‘‘
  • This class also has draft methods, which may change over time. They are not in stable releases, by default. To turn them on, use --enable-drafts. πŸ’…

πŸŽ€ The constructors

zsock_new

CZMQ_EXPORT zsock_t *
    zsock_new (int type);

Makes a new socket. Returns the new socket, or NULL if it couldn't be created.

⚠️ Not me warning you about this: the symbol zsock_new (and the other constructors/destructors for zsock) gets redirected to the *_checked variant, which enables intelligent socket leak detection. This can have performance implications if you use a LOT of sockets. To turn off this redirection behaviour, define ZSOCK_NOCHECK.

zsock_new_pub

CZMQ_EXPORT zsock_t *
    zsock_new_pub (const char *endpoint);

Makes a PUB socket. Default action is bind. πŸ“‘

zsock_new_sub

CZMQ_EXPORT zsock_t *
    zsock_new_sub (const char *endpoint, const char *subscribe);

Makes a SUB socket, and optionally subscribes to some prefix string. Default action is connect. πŸ‘‚

zsock_new_req

CZMQ_EXPORT zsock_t *
    zsock_new_req (const char *endpoint);

Makes a REQ socket. Default action is connect. πŸ™‹

zsock_new_rep

CZMQ_EXPORT zsock_t *
    zsock_new_rep (const char *endpoint);

Makes a REP socket. Default action is bind. πŸ’¬

zsock_new_dealer

CZMQ_EXPORT zsock_t *
    zsock_new_dealer (const char *endpoint);

Makes a DEALER socket. Default action is connect. πŸƒ

zsock_new_router

CZMQ_EXPORT zsock_t *
    zsock_new_router (const char *endpoint);

Makes a ROUTER socket. Default action is bind. πŸ›£οΈ

zsock_new_push

CZMQ_EXPORT zsock_t *
    zsock_new_push (const char *endpoint);

Makes a PUSH socket. Default action is connect. ⬆️

zsock_new_pull

CZMQ_EXPORT zsock_t *
    zsock_new_pull (const char *endpoint);

Makes a PULL socket. Default action is bind. ⬇️

zsock_new_xpub

CZMQ_EXPORT zsock_t *
    zsock_new_xpub (const char *endpoint);

Makes an XPUB socket. Default action is bind. πŸ“’

zsock_new_xsub

CZMQ_EXPORT zsock_t *
    zsock_new_xsub (const char *endpoint);

Makes an XSUB socket. Default action is connect. πŸ”‡

zsock_new_pair

CZMQ_EXPORT zsock_t *
    zsock_new_pair (const char *endpoint);

Makes a PAIR socket. Default action is connect. πŸ‘―

zsock_new_stream

CZMQ_EXPORT zsock_t *
    zsock_new_stream (const char *endpoint);

Makes a STREAM socket. Default action is connect. 🌊

zsock_destroy

CZMQ_EXPORT void
    zsock_destroy (zsock_t **self_p);

Destroys the socket. You must use this for any socket created via the zsock_new method. πŸ—‘οΈ


🌈 Binding, connecting, attaching

zsock_bind

CZMQ_EXPORT int
    zsock_bind (zsock_t *self, const char *format, ...) CHECK_PRINTF (2);

Binds a socket to a formatted endpoint. For tcp:// endpoints, it supports ephemeral ports, if you specify the port number as "*". By default zsock uses the IANA designated range from C000 (49152) to FFFF (65535). To override this range, follow the "*" with "[first-last]". Either or both first and last may be empty. To bind to a random port within the range, use "!" in place of "*". 🎯

Examples, bestie, take notes:

tcp://127.0.0.1:*           bind to first free port from C000 up
tcp://127.0.0.1:!           bind to random port from C000 to FFFF
tcp://127.0.0.1:*[60000-]   bind to first free port from 60000 up
tcp://127.0.0.1:![-60000]   bind to random port from C000 to 60000
tcp://127.0.0.1:![55000-55999]
                            bind to random port from 55000 to 55999

On success, it returns the actual port number used, for tcp:// endpoints, and 0 for other transports. On failure, it returns -1. Note that when using ephemeral ports, a port may be reused by different services without clients being aware. Protocols that run on ephemeral ports should take this into account. πŸ‘€

zsock_endpoint

CZMQ_EXPORT const char *
    zsock_endpoint (zsock_t *self);

Returns the last bound endpoint, if any. 🏷️

zsock_unbind

CZMQ_EXPORT int
    zsock_unbind (zsock_t *self, const char *format, ...) CHECK_PRINTF (2);

Unbinds a socket from a formatted endpoint. Returns 0 if OK, -1 if the endpoint was invalid or the function isn't supported. πŸ™…

zsock_connect

CZMQ_EXPORT int
    zsock_connect (zsock_t *self, const char *format, ...) CHECK_PRINTF (2);

Connects a socket to a formatted endpoint. Returns 0 if OK, -1 if the endpoint was invalid. πŸ”Œ

zsock_disconnect

CZMQ_EXPORT int
    zsock_disconnect (zsock_t *self, const char *format, ...) CHECK_PRINTF (2);

Disconnects a socket from a formatted endpoint. Returns 0 if OK, -1 if the endpoint was invalid or the function isn't supported. βœ‚οΈ

zsock_attach

CZMQ_EXPORT int
    zsock_attach (zsock_t *self, const char *endpoints, bool serverish);

Attaches a socket to zero or more endpoints. If endpoints is not null, it parses as a list of ZeroMQ endpoints, separated by commas, and prefixed by '@' (to bind the socket) or '>' (to connect the socket). Returns 0 if all endpoints were valid, or -1 if there was a syntax error. If the endpoint does not start with '@' or '>', the serverish argument defines whether it is used to bind (serverish = true) or connect (serverish = false). 🧲

zsock_type_str

CZMQ_EXPORT const char *
    zsock_type_str (zsock_t *self);

Returns the socket type as a printable constant string. πŸ”€


πŸ’Œ Sending and receiving 'pictures'

zsock_send

CZMQ_EXPORT int
    zsock_send (void *self, const char *picture, ...);

Sends a 'picture' message to the socket (or actor). The picture is a string that defines the type of each frame. This makes it easy to send a complex multiframe message in one call. πŸ–ΌοΈ The picture can contain any of these characters, each corresponding to one or two arguments:

i = int (signed)
1 = uint8_t
2 = uint16_t
4 = uint32_t
8 = uint64_t
s = char *
b = byte *, size_t (2 arguments)
c = zchunk_t *
f = zframe_t *
h = zhashx_t *
l = zlistx_t * (DRAFT)
U = zuuid_t *
p = void * (sends the pointer value, only meaningful over inproc)
m = zmsg_t * (sends all frames in the zmsg)
z = sends zero-sized frame (0 arguments)
u = uint (deprecated)

Note that s, b, c, and f are encoded the same way and the choice is offered as a convenience to the sender, which may or may not already have data in a zchunk or zframe. It does not change or take ownership of any arguments. Returns 0 if successful, -1 if sending failed for any reason. πŸ’€

zsock_vsend

CZMQ_EXPORT int
    zsock_vsend (void *self, const char *picture, va_list argptr);

Sends a 'picture' message to the socket (or actor). This is the va_list version of zsock_send (), so please go read its documentation for the details. πŸ“œ

zsock_recv

CZMQ_EXPORT int
    zsock_recv (void *self, const char *picture, ...);

Receives a 'picture' message to the socket (or actor). See zsock_send for the format and meaning of the picture. Returns the picture elements into a series of pointers as provided by the caller: πŸ“₯

i = int * (stores signed integer)
4 = uint32_t * (stores 32-bit unsigned integer)
8 = uint64_t * (stores 64-bit unsigned integer)
s = char ** (allocates new string)
b = byte **, size_t * (2 arguments) (allocates memory)
c = zchunk_t ** (creates zchunk)
f = zframe_t ** (creates zframe)
U = zuuid_t * (creates a zuuid with the data)
h = zhashx_t ** (creates zhashx)
l = zlistx_t ** (creates zlistx) (DRAFT)
p = void ** (stores pointer)
m = zmsg_t ** (creates a zmsg with the remaining frames)
z = null, asserts empty frame (0 arguments)
u = uint * (stores unsigned integer, deprecated)

Note that zsock_recv creates the returned objects, and the caller must destroy them when finished with them. The supplied pointers do not need to be initialized. Returns 0 if successful, or -1 if it failed to recv a message, in which case the pointers are not modified. When message frames are truncated (a short message), it sets return values to zero/null. If an argument pointer is NULL, it does not store any value (skips it). An 'n' picture matches an empty frame; if the message does not match, the method will return -1. 😭

zsock_vrecv

CZMQ_EXPORT int
    zsock_vrecv (void *self, const char *picture, va_list argptr);

Receives a 'picture' message from the socket (or actor). This is the va_list version of zsock_recv (), so please consult its documentation for the details. 🫧

zsock_bsend

CZMQ_EXPORT int
    zsock_bsend (void *self, const char *picture, ...);

Sends a binary encoded 'picture' message to the socket (or actor). This method is similar to zsock_send, except the arguments are encoded in a binary format that is compatible with zproto, and is designed to reduce memory allocations. The pattern argument is a string that defines the type of each argument. Supports these argument types: 🧬

pattern    C type                  zproto type:
   1       uint8_t                 type = "number" size = "1"
   2       uint16_t                type = "number" size = "2"
   4       uint32_t                type = "number" size = "3"
   8       uint64_t                type = "number" size = "4"
   s       char *, 0-255 chars     type = "string"
   S       char *, 0-2^32-1 chars  type = "longstr"
   c       zchunk_t *              type = "chunk"
   f       zframe_t *              type = "frame"
   u       zuuid_t *               type = "uuid"
   m       zmsg_t *                type = "msg"
   p       void *, sends pointer value, only over inproc

Does not change or take ownership of any arguments. Returns 0 if successful, -1 if sending failed for any reason. πŸ”₯

okay so zsock_brecv is zsock_recv's feral little sibling πŸ’… it pulls a binary encoded 'picture' message off the socket (or the actor), and the whole reason it exists is that it's compatible with zproto and designed to reduce memory allocations. less mallocing, less crying, slay.

the picture argument is a string that defines the type of each argument β€” and if you wanna know which argument types are even supported, go read zsock_bsend, bestie, it's all there. one thing you cannot skip: all arguments must be pointers, because this call sets them to point to values that are held on a per-socket basis.

and now the ✨ownership tea✨ per type, because this is where people get wrecked:

  • for types 1, 2, 4 and 8 β€” the caller must allocate the memory itself before calling zsock_brecv.
  • for type S β€” the caller must free the value once finished with it, because zsock_brecv will allocate the buffer.
  • for type s β€” the caller must not free the value, because it is stored in a local cache for performance purposes. do not touch it. hands off. πŸ™ˆ
  • for types c, f, u and m β€” the caller must call the appropriate destructor depending on the object, because zsock_brecv will create new objects.
  • for type p β€” the caller must coordinate with the sender, because it's just a pointer value being passed. πŸ‘€
CZMQ_EXPORT int
    zsock_brecv (void *self, const char *picture, ...);

next up, zsock_set_unbounded β€” this flips your socket over to unbounded pipes, aka HWM=0. it works across all versions of ZeroMQ, which is iconic of it honestly. it also takes a polymorphic socket reference.

bestie. only reach for this when you are totally certain the message volume can fit in memory. no cap. πŸ”₯
CZMQ_EXPORT void
    zsock_set_unbounded (void *self);

zsock_signal sends a signal over a socket. a signal is a short message that carries a success/failure code β€” by convention, 0 means OK. signals are encoded so they're distinguishable from "normal" messages, so nobody gets confused. it accepts a zsock_t or a zactor_t argument, and it returns 0 if successful, -1 if the signal could not be sent. takes a polymorphic socket reference.

CZMQ_EXPORT int
    zsock_signal (void *self, byte status);

zsock_wait is the other half of that story β€” you wait on a signal. use it to coordinate between threads, over pipe pairs. it blocks until the signal is received. returns -1 on error, 0 or greater on success. accepts a zsock_t or a zactor_t as argument. takes a polymorphic socket reference.

CZMQ_EXPORT int
    zsock_wait (void *self);

zsock_flush β€” if there's a partial message still waiting on the socket, this removes and discards it. lowkey a lifesaver when you're reading partial messages and you need to get at specific message types.

CZMQ_EXPORT void
    zsock_flush (void *self);

zsock_is probes the supplied object and reports whether it looks like a zsock_t. takes a polymorphic socket reference.

CZMQ_EXPORT bool
    zsock_is (void *self);

zsock_resolve probes the supplied reference and does the little detective work for you πŸ•΅οΈ β€” if it looks like a zsock_t instance, you get the underlying libzmq socket handle back; else if it looks like a file descriptor, you get NULL; else if it looks like a libzmq socket handle, you get the supplied value back. takes a polymorphic socket reference.

CZMQ_EXPORT void *
    zsock_resolve (void *self);

okay bestie, now we're in socket option territory and there are a LOT of them. buckle up. πŸŽ€

  • zsock_priority β€” get socket option priority. available from libzmq 4.3.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT int
    zsock_priority (void *self);
  • zsock_set_priority β€” set socket option priority. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_priority (void *self, int priority);
  • zsock_reconnect_stop β€” get socket option reconnect_stop. available from libzmq 4.3.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT int
    zsock_reconnect_stop (void *self);
  • zsock_set_reconnect_stop β€” set socket option reconnect_stop. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_reconnect_stop (void *self, int reconnect_stop);
  • zsock_set_only_first_subscribe β€” set socket option only_first_subscribe. available from libzmq 4.3.0. (no getter for this one, she's write-only πŸ’…)
CZMQ_EXPORT void
    zsock_set_only_first_subscribe (void *self, int only_first_subscribe);
  • zsock_set_hello_msg β€” set socket option hello_msg. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_hello_msg (void *self, zframe_t *hello_msg);
  • zsock_set_disconnect_msg β€” set socket option disconnect_msg. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_disconnect_msg (void *self, zframe_t *disconnect_msg);
  • zsock_set_wss_trust_system β€” set socket option wss_trust_system. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_wss_trust_system (void *self, int wss_trust_system);
  • zsock_set_wss_hostname β€” set socket option wss_hostname. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_wss_hostname (void *self, const char *wss_hostname);
  • zsock_set_wss_trust_pem β€” set socket option wss_trust_pem. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_wss_trust_pem (void *self, const char *wss_trust_pem);
  • zsock_set_wss_cert_pem β€” set socket option wss_cert_pem. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_wss_cert_pem (void *self, const char *wss_cert_pem);
  • zsock_set_wss_key_pem β€” set socket option wss_key_pem. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_wss_key_pem (void *self, const char *wss_key_pem);
  • zsock_out_batch_size β€” get socket option out_batch_size. available from libzmq 4.3.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT int
    zsock_out_batch_size (void *self);
  • zsock_set_out_batch_size β€” set socket option out_batch_size. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_out_batch_size (void *self, int out_batch_size);
  • zsock_in_batch_size β€” get socket option in_batch_size. available from libzmq 4.3.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT int
    zsock_in_batch_size (void *self);
  • zsock_set_in_batch_size β€” set socket option in_batch_size. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_in_batch_size (void *self, int in_batch_size);
  • zsock_socks_password β€” get socket option socks_password. available from libzmq 4.3.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT char *
    zsock_socks_password (void *self);
  • zsock_set_socks_password β€” set socket option socks_password. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_socks_password (void *self, const char *socks_password);
  • zsock_socks_username β€” get socket option socks_username. available from libzmq 4.3.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT char *
    zsock_socks_username (void *self);
  • zsock_set_socks_username β€” set socket option socks_username. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_socks_username (void *self, const char *socks_username);
  • zsock_set_xpub_manual_last_value β€” set socket option xpub_manual_last_value. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_xpub_manual_last_value (void *self, int xpub_manual_last_value);
  • zsock_router_notify β€” get socket option router_notify. available from libzmq 4.3.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT int
    zsock_router_notify (void *self);
  • zsock_set_router_notify β€” set socket option router_notify. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_router_notify (void *self, int router_notify);
  • zsock_multicast_loop β€” get socket option multicast_loop. available from libzmq 4.3.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT int
    zsock_multicast_loop (void *self);
  • zsock_set_multicast_loop β€” set socket option multicast_loop. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_multicast_loop (void *self, int multicast_loop);
  • zsock_metadata β€” get socket option metadata. available from libzmq 4.3.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT char *
    zsock_metadata (void *self);
  • zsock_set_metadata β€” set socket option metadata. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_metadata (void *self, const char *metadata);
  • zsock_loopback_fastpath β€” get socket option loopback_fastpath. available from libzmq 4.3.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT int
    zsock_loopback_fastpath (void *self);
  • zsock_set_loopback_fastpath β€” set socket option loopback_fastpath. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_loopback_fastpath (void *self, int loopback_fastpath);
  • zsock_zap_enforce_domain β€” get socket option zap_enforce_domain. available from libzmq 4.3.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT int
    zsock_zap_enforce_domain (void *self);
  • zsock_set_zap_enforce_domain β€” set socket option zap_enforce_domain. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_zap_enforce_domain (void *self, int zap_enforce_domain);
  • zsock_gssapi_principal_nametype β€” get socket option gssapi_principal_nametype. available from libzmq 4.3.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT int
    zsock_gssapi_principal_nametype (void *self);
  • zsock_set_gssapi_principal_nametype β€” set socket option gssapi_principal_nametype. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_gssapi_principal_nametype (void *self, int gssapi_principal_nametype);
  • zsock_gssapi_service_principal_nametype β€” get socket option gssapi_service_principal_nametype. available from libzmq 4.3.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT int
    zsock_gssapi_service_principal_nametype (void *self);
  • zsock_set_gssapi_service_principal_nametype β€” set socket option gssapi_service_principal_nametype. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_gssapi_service_principal_nametype (void *self, int gssapi_service_principal_nametype);
  • zsock_bindtodevice β€” get socket option bindtodevice. available from libzmq 4.3.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT char *
    zsock_bindtodevice (void *self);
  • zsock_set_bindtodevice β€” set socket option bindtodevice. available from libzmq 4.3.0.
CZMQ_EXPORT void
    zsock_set_bindtodevice (void *self, const char *bindtodevice);
  • zsock_heartbeat_ivl β€” get socket option heartbeat_ivl. available from libzmq 4.2.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT int
    zsock_heartbeat_ivl (void *self);
  • zsock_set_heartbeat_ivl β€” set socket option heartbeat_ivl. available from libzmq 4.2.0.
CZMQ_EXPORT void
    zsock_set_heartbeat_ivl (void *self, int heartbeat_ivl);
  • zsock_heartbeat_ttl β€” get socket option heartbeat_ttl. available from libzmq 4.2.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT int
    zsock_heartbeat_ttl (void *self);
  • zsock_set_heartbeat_ttl β€” set socket option heartbeat_ttl. available from libzmq 4.2.0.
CZMQ_EXPORT void
    zsock_set_heartbeat_ttl (void *self, int heartbeat_ttl);
  • zsock_heartbeat_timeout β€” get socket option heartbeat_timeout. available from libzmq 4.2.0. caller owns the return value and must destroy it when done.
CZMQ_EXPORT int
    zsock_heartbeat_timeout (void *self);
  • zsock_set_heartbeat_timeout β€” set socket option heartbeat_timeout. available from libzmq 4.2.0.
CZMQ_EXPORT void
    zsock_set_heartbeat_timeout (void *self, int heartbeat_timeout);

And the socket-option tour just keeps going, bestie β€” no intermission, no skipping, we're doing every single one πŸ’…

  • CZMQ_EXPORT int zsock_use_fd (void *self); β€” grabs the socket option use_fd. Available from libzmq 4.2.0. Caller owns the return value and must destroy it when done 🫢
  • CZMQ_EXPORT void zsock_set_use_fd (void *self, int use_fd); β€” sets the socket option use_fd. Available from libzmq 4.2.0. ✨
  • CZMQ_EXPORT void zsock_set_xpub_manual (void *self, int xpub_manual); β€” sets the socket option xpub_manual. Available from libzmq 4.2.0.
  • CZMQ_EXPORT void zsock_set_xpub_welcome_msg (void *self, const char *xpub_welcome_msg); β€” sets the socket option xpub_welcome_msg, and yeah it takes a const char *. Available from libzmq 4.2.0 πŸŽ€
  • CZMQ_EXPORT void zsock_set_stream_notify (void *self, int stream_notify); β€” sets the socket option stream_notify. Available from libzmq 4.2.0.
  • CZMQ_EXPORT int zsock_invert_matching (void *self); β€” gets the socket option invert_matching. Available from libzmq 4.2.0. Caller owns the return value and must destroy it when done β€” that's on you, not on me 😭
  • CZMQ_EXPORT void zsock_set_invert_matching (void *self, int invert_matching); β€” sets the socket option invert_matching. Available from libzmq 4.2.0.
  • CZMQ_EXPORT void zsock_set_xpub_verboser (void *self, int xpub_verboser); β€” sets the socket option xpub_verboser. Available from libzmq 4.2.0.
  • CZMQ_EXPORT int zsock_connect_timeout (void *self); β€” gets the socket option connect_timeout. Available from libzmq 4.2.0. Caller owns the return value and must destroy it when done.
  • CZMQ_EXPORT void zsock_set_connect_timeout (void *self, int connect_timeout); β€” sets the socket option connect_timeout. Available from libzmq 4.2.0 ✨
  • CZMQ_EXPORT int zsock_tcp_maxrt (void *self); β€” gets the socket option tcp_maxrt. Available from libzmq 4.2.0. Caller owns the return value and must destroy it when done.
  • CZMQ_EXPORT void zsock_set_tcp_maxrt (void *self, int tcp_maxrt); β€” sets the socket option tcp_maxrt. Available from libzmq 4.2.0.
  • CZMQ_EXPORT int zsock_thread_safe (void *self); β€” gets the socket option thread_safe. Available from libzmq 4.2.0. Caller owns the return value and must destroy it when done. (Getter only here, no setter, don't come for me πŸ™ˆ)
  • CZMQ_EXPORT int zsock_multicast_maxtpdu (void *self); β€” gets the socket option multicast_maxtpdu. Available from libzmq 4.2.0. Caller owns the return value and must destroy it when done.
  • CZMQ_EXPORT void zsock_set_multicast_maxtpdu (void *self, int multicast_maxtpdu); β€” sets the socket option multicast_maxtpdu. Available from libzmq 4.2.0.
  • CZMQ_EXPORT int zsock_vmci_buffer_size (void *self); β€” gets the socket option vmci_buffer_size. Available from libzmq 4.2.0. Caller owns the return value and must destroy it when done 🫢
  • CZMQ_EXPORT void zsock_set_vmci_buffer_size (void *self, int vmci_buffer_size); β€” sets the socket option vmci_buffer_size. Available from libzmq 4.2.0.
  • CZMQ_EXPORT int zsock_vmci_buffer_min_size (void *self); β€” gets the socket option vmci_buffer_min_size. Available from libzmq 4.2.0. Caller owns the return value and must destroy it when done.
  • CZMQ_EXPORT void zsock_set_vmci_buffer_min_size (void *self, int vmci_buffer_min_size); β€” sets the socket option vmci_buffer_min_size. Available from libzmq 4.2.0.
  • CZMQ_EXPORT int zsock_vmci_buffer_max_size (void *self); β€” gets the socket option vmci_buffer_max_size. Available from libzmq 4.2.0. Caller owns the return value and must destroy it when done.
  • CZMQ_EXPORT void zsock_set_vmci_buffer_max_size (void *self, int vmci_buffer_max_size); β€” sets the socket option vmci_buffer_max_size. Available from libzmq 4.2.0.
  • CZMQ_EXPORT int zsock_vmci_connect_timeout (void *self); β€” gets the socket option vmci_connect_timeout. Available from libzmq 4.2.0. Caller owns the return value and must destroy it when done.
  • CZMQ_EXPORT void zsock_set_vmci_connect_timeout (void *self, int vmci_connect_timeout); β€” sets the socket option vmci_connect_timeout. Available from libzmq 4.2.0 ✨

Newer-version drop incoming β€” the 4.1.0 girlies 🌸

  • CZMQ_EXPORT int zsock_tos (void *self); β€” gets the socket option tos. Available from libzmq 4.1.0. Caller owns the return value and must destroy it when done.
  • CZMQ_EXPORT void zsock_set_tos (void *self, int tos); β€” sets the socket option tos. Available from libzmq 4.1.0.
  • CZMQ_EXPORT void zsock_set_router_handover (void *self, int router_handover); β€” sets the socket option router_handover. Available from libzmq 4.1.0.
  • CZMQ_EXPORT void zsock_set_connect_rid (void *self, const char *connect_rid); β€” sets the socket option connect_rid. Available from libzmq 4.1.0.
  • CZMQ_EXPORT void zsock_set_connect_rid_bin (void *self, const byte *connect_rid); β€” sets the socket option connect_rid from 32-octet binary. Available from libzmq 4.1.0 πŸ’…
  • CZMQ_EXPORT int zsock_handshake_ivl (void *self); β€” gets the socket option handshake_ivl. Available from libzmq 4.1.0. Caller owns the return value and must destroy it when done.
  • CZMQ_EXPORT void zsock_set_handshake_ivl (void *self, int handshake_ivl); β€” sets the socket option handshake_ivl. Available from libzmq 4.1.0.
  • CZMQ_EXPORT char * zsock_socks_proxy (void *self); β€” gets the socket option socks_proxy, and yes it hands you back a char *. Available from libzmq 4.1.0. Caller owns the return value and must destroy it when done 😭
  • CZMQ_EXPORT void zsock_set_socks_proxy (void *self, const char *socks_proxy); β€” sets the socket option socks_proxy. Available from libzmq 4.1.0.
  • CZMQ_EXPORT void zsock_set_xpub_nodrop (void *self, int xpub_nodrop); β€” sets the socket option xpub_nodrop. Available from libzmq 4.1.0.

And now the OGs β€” the 4.0.0 lineup, the founding mothers πŸ‘‘

  • CZMQ_EXPORT void zsock_set_router_mandatory (void *self, int router_mandatory); β€” sets the socket option router_mandatory. Available from libzmq 4.0.0.
  • CZMQ_EXPORT void zsock_set_probe_router (void *self, int probe_router); β€” sets the socket option probe_router. Available from libzmq 4.0.0.
  • CZMQ_EXPORT void zsock_set_req_relaxed (void *self, int req_relaxed); β€” sets the socket option req_relaxed. Available from libzmq 4.0.0.
  • CZMQ_EXPORT void zsock_set_req_correlate (void *self, int req_correlate); β€” sets the socket option req_correlate. Available from libzmq 4.0.0.
  • CZMQ_EXPORT void zsock_set_conflate (void *self, int conflate); β€” sets the socket option conflate. Available from libzmq 4.0.0.
  • CZMQ_EXPORT char * zsock_zap_domain (void *self); β€” gets the socket option zap_domain, returned as a char *. Available from libzmq 4.0.0. Caller owns the return value and must destroy it when done 🫢
  • CZMQ_EXPORT void zsock_set_zap_domain (void *self, const char *zap_domain); β€” sets the socket option zap_domain. Available from libzmq 4.0.0.
  • CZMQ_EXPORT int zsock_mechanism (void *self); β€” gets the socket option mechanism. Available from libzmq 4.0.0. Caller owns the return value and must destroy it when done.
  • CZMQ_EXPORT int zsock_plain_server (void *self); β€” gets the socket option plain_server. Available from libzmq 4.0.0. Caller owns the return value and must destroy it when done.
  • CZMQ_EXPORT void zsock_set_plain_server (void *self, int plain_server); β€” sets the socket option plain_server. Available from libzmq 4.0.0.
  • CZMQ_EXPORT char * zsock_plain_username (void *self); β€” gets the socket option plain_username, and it's a char * bestie. Available from libzmq 4.0.0. Caller owns the return value and must destroy it when done ✨
  • CZMQ_EXPORT void zsock_set_plain_username (void *self, const char *plain_username); β€” sets the socket option plain_username. Available from libzmq 4.0.0.
  • CZMQ_EXPORT char * zsock_plain_password (void *self); β€” gets the socket option plain_password, handed back as a char *. Available from libzmq 4.0.0. Caller owns the return value and must destroy it when done πŸ™ˆ
  • CZMQ_EXPORT void zsock_set_plain_password (void *self, const char *plain_password); β€” sets the socket option plain_password. Available from libzmq 4.0.0.
  • CZMQ_EXPORT int zsock_curve_server (void *self); β€” gets the socket option curve_server. Available from libzmq 4.0.0. Caller owns the return value and must destroy it when done.
  • CZMQ_EXPORT void zsock_set_curve_server (void *self, int curve_server); β€” sets the socket option curve_server. Available from libzmq 4.0.0.
  • CZMQ_EXPORT char * zsock_curve_publickey (void *self); β€” gets the socket option curve_publickey, as a char *. Available from libzmq 4.0.0. Caller owns the return value and must destroy it when done.
  • CZMQ_EXPORT void zsock_set_curve_publickey (void *self, const char *curve_publickey); β€” sets the socket option curve_publickey. Available from libzmq 4.0.0.
  • CZMQ_EXPORT void zsock_set_curve_publickey_bin (void *self, const byte *curve_publickey); β€” sets the socket option curve_publickey from 32-octet binary. Available from libzmq 4.0.0 πŸ’…
  • CZMQ_EXPORT char * zsock_curve_secretkey (void *self); β€” gets the socket option curve_secretkey, returned as a char *. Available from libzmq 4.0.0. Caller owns the return value and must destroy it when done 😭
  • CZMQ_EXPORT void zsock_set_curve_secretkey (void *self, const char *curve_secretkey); β€” sets the socket option curve_secretkey. Available from libzmq 4.0.0.
  • CZMQ_EXPORT void zsock_set_curve_secretkey_bin (void *self, const byte *curve_secretkey); β€” sets the socket option curve_secretkey from 32-octet binary. Available from libzmq 4.0.0.
  • CZMQ_EXPORT char * zsock_curve_serverkey (void *self); β€” gets the socket option curve_serverkey, and yep, char * again. Available from libzmq 4.0.0. Caller owns the return value and must destroy it when done 🫢
  • CZMQ_EXPORT void zsock_set_curve_serverkey (void *self, const char *curve_serverkey); β€” sets the socket option curve_serverkey. Available from libzmq 4.0.0.
  • CZMQ_EXPORT void zsock_set_curve_serverkey_bin (void *self, const byte *curve_serverkey); β€” sets the socket option curve_serverkey from 32-octet binary. Available from libzmq 4.0.0 ✨
  • CZMQ_EXPORT int zsock_gssapi_server (void *self); β€” gets the socket option gssapi_server. Available from libzmq 4.0.0. Caller owns the return value and must destroy it when done.
  • CZMQ_EXPORT void zsock_set_gssapi_server (void *self, int gssapi_server); β€” sets the socket option gssapi_server. Available from libzmq 4.0.0. 🌈

okay bestie we're back in the option list and there is so much more πŸ’– quick reminder before we dive: every getter down here hands you a value that you now own β€” caller owns return value and must destroy it when done. no leaks, that's not the vibe 🫢


🌸 gssapi_plaintext β€” Available from libzmq 4.0.0.

CZMQ_EXPORT int
    zsock_gssapi_plaintext (void *self);

CZMQ_EXPORT void
    zsock_set_gssapi_plaintext (void *self, int gssapi_plaintext);

getter hands you an int, and the return value is yours β€” caller owns return value and must destroy it when done πŸ’…

πŸ” gssapi_principal β€” Available from libzmq 4.0.0.

CZMQ_EXPORT char *
    zsock_gssapi_principal (void *self);

CZMQ_EXPORT void
    zsock_set_gssapi_principal (void *self, const char *gssapi_principal);

yep, this one's a char *, and caller owns return value and must destroy it when done 🫢

πŸ” gssapi_service_principal β€” Available from libzmq 4.0.0.

CZMQ_EXPORT char *
    zsock_gssapi_service_principal (void *self);

CZMQ_EXPORT void
    zsock_set_gssapi_service_principal (void *self, const char *gssapi_service_principal);

also a char * bestie, also caller owns return value and must destroy it when done ✨


🌐 ipv6 β€” Available from libzmq 4.0.0.

CZMQ_EXPORT int
    zsock_ipv6 (void *self);

CZMQ_EXPORT void
    zsock_set_ipv6 (void *self, int ipv6);

int in, int out, and the getter's return value belongs to the caller, who must destroy it when done πŸ’œ

⚑ immediate β€” Available from libzmq 4.0.0.

CZMQ_EXPORT int
    zsock_immediate (void *self);

CZMQ_EXPORT void
    zsock_set_immediate (void *self, int immediate);

same deal β€” caller owns return value and must destroy it when done πŸ”₯

πŸ“€ sndhwm β€” Available from libzmq 3.0.0.

CZMQ_EXPORT int
    zsock_sndhwm (void *self);

CZMQ_EXPORT void
    zsock_set_sndhwm (void *self, int sndhwm);

caller owns return value and must destroy it when done, no cap πŸŽ€

πŸ“₯ rcvhwm β€” Available from libzmq 3.0.0.

CZMQ_EXPORT int
    zsock_rcvhwm (void *self);

CZMQ_EXPORT void
    zsock_set_rcvhwm (void *self, int rcvhwm);

yes bestie, again: caller owns return value and must destroy it when done 🌸

πŸ“ maxmsgsize β€” Available from libzmq 3.0.0.

CZMQ_EXPORT int
    zsock_maxmsgsize (void *self);

CZMQ_EXPORT void
    zsock_set_maxmsgsize (void *self, int maxmsgsize);

caller owns return value and must destroy it when done πŸ’«

πŸ“‘ multicast_hops β€” Available from libzmq 3.0.0.

CZMQ_EXPORT int
    zsock_multicast_hops (void *self);

CZMQ_EXPORT void
    zsock_set_multicast_hops (void *self, int multicast_hops);

getter return value = yours, caller owns return value and must destroy it when done πŸ¦‹


πŸ“£ xpub_verbose β€” Available from libzmq 3.0.0.

CZMQ_EXPORT void
    zsock_set_xpub_verbose (void *self, int xpub_verbose);

set-only bestie, there's no getter for this one β€” set it and move on ✨


πŸ’“ tcp_keepalive β€” Available from libzmq 3.0.0.

CZMQ_EXPORT int
    zsock_tcp_keepalive (void *self);

CZMQ_EXPORT void
    zsock_set_tcp_keepalive (void *self, int tcp_keepalive);

caller owns return value and must destroy it when done 🫢

πŸ’“ tcp_keepalive_idle β€” Available from libzmq 3.0.0.

CZMQ_EXPORT int
    zsock_tcp_keepalive_idle (void *self);

CZMQ_EXPORT void
    zsock_set_tcp_keepalive_idle (void *self, int tcp_keepalive_idle);

and yeah, caller owns return value and must destroy it when done πŸ’–

πŸ’“ tcp_keepalive_cnt β€” Available from libzmq 3.0.0.

CZMQ_EXPORT int
    zsock_tcp_keepalive_cnt (void *self);

CZMQ_EXPORT void
    zsock_set_tcp_keepalive_cnt (void *self, int tcp_keepalive_cnt);

caller owns return value and must destroy it when done, iykyk πŸ’…

πŸ’“ tcp_keepalive_intvl β€” Available from libzmq 3.0.0.

CZMQ_EXPORT int
    zsock_tcp_keepalive_intvl (void *self);

CZMQ_EXPORT void
    zsock_set_tcp_keepalive_intvl (void *self, int tcp_keepalive_intvl);

one more time for the people in the back: caller owns return value and must destroy it when done 🌈

🎫 tcp_accept_filter β€” Available from libzmq 3.0.0.

CZMQ_EXPORT char *
    zsock_tcp_accept_filter (void *self);

CZMQ_EXPORT void
    zsock_set_tcp_accept_filter (void *self, const char *tcp_accept_filter);

char * energy ✨ caller owns return value and must destroy it when done

πŸ“ last_endpoint β€” Available from libzmq 3.0.0.

CZMQ_EXPORT char *
    zsock_last_endpoint (void *self);

getter only, no setter here β€” and obviously caller owns return value and must destroy it when done πŸ‘‘

πŸ› οΈ router_raw β€” Available from libzmq 3.0.0.

CZMQ_EXPORT void
    zsock_set_router_raw (void *self, int router_raw);

also set-only πŸ’… no getter in sight

4️⃣ ipv4only β€” Available from libzmq 3.0.0.

CZMQ_EXPORT int
    zsock_ipv4only (void *self);

CZMQ_EXPORT void
    zsock_set_ipv4only (void *self, int ipv4only);

caller owns return value and must destroy it when done πŸŽ€

⏳ delay_attach_on_connect β€” Available from libzmq 3.0.0.

CZMQ_EXPORT void
    zsock_set_delay_attach_on_connect (void *self, int delay_attach_on_connect);

set-only, bestie β€” no getter for this one πŸ”₯


🚨 okay so everything from here down is the old crowd β€” these are the legacy options. The hwm, swap, recovery_ivl_msec and mcast_loop ones only existed in libzmq 2.0.0 to 3.0.0, so if you're on modern libzmq, don't come crying to me when they're not there 😭

πŸ“¦ hwm β€” Available from libzmq 2.0.0 to 3.0.0.

CZMQ_EXPORT int
    zsock_hwm (void *self);

CZMQ_EXPORT void
    zsock_set_hwm (void *self, int hwm);

legacy era πŸ’€ caller owns return value and must destroy it when done

πŸ”„ swap β€” Available from libzmq 2.0.0 to 3.0.0.

CZMQ_EXPORT int
    zsock_swap (void *self);

CZMQ_EXPORT void
    zsock_set_swap (void *self, int swap);

caller owns return value and must destroy it when done 🫢

🧲 affinity β€” Available from libzmq 2.0.0.

CZMQ_EXPORT int
    zsock_affinity (void *self);

CZMQ_EXPORT void
    zsock_set_affinity (void *self, int affinity);

caller owns return value and must destroy it when done ✨

πŸͺͺ identity β€” Available from libzmq 2.0.0.

CZMQ_EXPORT char *
    zsock_identity (void *self);

CZMQ_EXPORT void
    zsock_set_identity (void *self, const char *identity);

char * so you already know: caller owns return value and must destroy it when done πŸ’–

⏱️ rate β€” Available from libzmq 2.0.0.

CZMQ_EXPORT int
    zsock_rate (void *self);

CZMQ_EXPORT void
    zsock_set_rate (void *self, int rate);

caller owns return value and must destroy it when done πŸ’…

🩹 recovery_ivl β€” Available from libzmq 2.0.0.

CZMQ_EXPORT int
    zsock_recovery_ivl (void *self);

CZMQ_EXPORT void
    zsock_set_recovery_ivl (void *self, int recovery_ivl);

caller owns return value and must destroy it when done πŸ¦‹

🩹 recovery_ivl_msec β€” Available from libzmq 2.0.0 to 3.0.0.

CZMQ_EXPORT int
    zsock_recovery_ivl_msec (void *self);

CZMQ_EXPORT void
    zsock_set_recovery_ivl_msec (void *self, int recovery_ivl_msec);

legacy again πŸ’€ caller owns return value and must destroy it when done

πŸ” mcast_loop β€” Available from libzmq 2.0.0 to 3.0.0.

CZMQ_EXPORT int
    zsock_mcast_loop (void *self);

CZMQ_EXPORT void
    zsock_set_mcast_loop (void *self, int mcast_loop);

caller owns return value and must destroy it when done 🌸

βŒ› rcvtimeo β€” Available from libzmq 2.2.0.

CZMQ_EXPORT int
    zsock_rcvtimeo (void *self);

CZMQ_EXPORT void
    zsock_set_rcvtimeo (void *self, int rcvtimeo);

caller owns return value and must destroy it when done ⭐

βŒ› sndtimeo β€” Available from libzmq 2.2.0.

CZMQ_EXPORT int
    zsock_sndtimeo (void *self);

CZMQ_EXPORT void
    zsock_set_sndtimeo (void *self, int sndtimeo);

caller owns return value and must destroy it when done πŸŽ€

πŸ«™ sndbuf β€” Available from libzmq 2.0.0.

CZMQ_EXPORT int
    zsock_sndbuf (void *self);

CZMQ_EXPORT void
    zsock_set_sndbuf (void *self, int sndbuf);

caller owns return value and must destroy it when done πŸ’œ

πŸ«™ rcvbuf β€” Available from libzmq 2.0.0.

CZMQ_EXPORT int
    zsock_rcvbuf (void *self);

CZMQ_EXPORT void
    zsock_set_rcvbuf (void *self, int rcvbuf);

caller owns return value and must destroy it when done 🌈

πŸ•°οΈ linger β€” Available from libzmq 2.0.0.

CZMQ_EXPORT int
    zsock_linger (void *self);

CZMQ_EXPORT void
    zsock_set_linger (void *self, int linger);

last one in this batch, and yes bestie β€” caller owns return value and must destroy it when done 🫢


...and the synopsis just keeps going, bestie, because of course it does πŸ’… Here's the rest of the declarations, nothing skipped, nothing merged.

Option getters and setters (vintage libzmq 2.0.0 energy)

  • zsock_reconnect_ivl β€” grab the reconnect_ivl socket option. Available since libzmq 2.0.0. The caller owns the return value and must destroy it when done, fr.
  • zsock_set_reconnect_ivl β€” set the reconnect_ivl socket option. Also libzmq 2.0.0.
CZMQ_EXPORT int
    zsock_reconnect_ivl (void *self);

CZMQ_EXPORT void
    zsock_set_reconnect_ivl (void *self, int reconnect_ivl);
  • zsock_reconnect_ivl_max β€” get the reconnect_ivl_max socket option. Libzmq 2.0.0. Caller owns the return value, destroy it when you're done 🫢
  • zsock_set_reconnect_ivl_max β€” set reconnect_ivl_max. Libzmq 2.0.0.
CZMQ_EXPORT int
    zsock_reconnect_ivl_max (void *self);

CZMQ_EXPORT void
    zsock_set_reconnect_ivl_max (void *self, int reconnect_ivl_max);
  • zsock_backlog β€” get the backlog socket option. Libzmq 2.0.0. Return value is yours, destroy it when you're finished.
  • zsock_set_backlog β€” set the backlog socket option. Libzmq 2.0.0.
CZMQ_EXPORT int
    zsock_backlog (void *self);

CZMQ_EXPORT void
    zsock_set_backlog (void *self, int backlog);
  • zsock_set_subscribe β€” set the subscribe socket option. Libzmq 2.0.0. (Yes it's set-only, bestie, there's no getter and that's just how it is πŸ’€)
  • zsock_set_unsubscribe β€” set the unsubscribe socket option. Libzmq 2.0.0.
CZMQ_EXPORT void
    zsock_set_subscribe (void *self, const char *subscribe);

CZMQ_EXPORT void
    zsock_set_unsubscribe (void *self, const char *unsubscribe);

The read-only girlies ✨ (getters, getters, getters)

  • zsock_type β€” get the type socket option. Libzmq 2.0.0. Caller owns the return value and must destroy it when done.
  • zsock_rcvmore β€” get the rcvmore socket option. Libzmq 2.0.0. Same deal: you own it, you destroy it.
  • zsock_fd β€” get the fd socket option, returned as a SOCKET. Libzmq 2.0.0. Caller owns the return value and must destroy it when done.
  • zsock_events β€” get the events socket option. Libzmq 2.0.0. You know the drill: caller owns it, destroy it when done.
CZMQ_EXPORT int
    zsock_type (void *self);

CZMQ_EXPORT int
    zsock_rcvmore (void *self);

CZMQ_EXPORT SOCKET
    zsock_fd (void *self);

CZMQ_EXPORT int
    zsock_events (void *self);

Self test πŸ§ͺ

  • zsock_test β€” the self test for this class. Takes a bool verbose so you can decide how chatty it gets.
CZMQ_EXPORT void
    zsock_test (bool verbose);

🚧 DRAFT API ALERT 🚧 Everything below lives inside #ifdef CZMQ_BUILD_DRAFT_API. Every single one of these is a draft method, for development use, may change without warning. Not a vibe check, an actual warning. Proceed with caution, queen πŸ‘‘
#ifdef CZMQ_BUILD_DRAFT_API

Draft socket constructors 🌸

  • zsock_new_server β€” make a SERVER socket. Default action is bind. Draft method, for development use, may change without warning.
  • zsock_new_client β€” make a CLIENT socket. Default action is connect. Draft method, for development use, may change without warning.
  • zsock_new_radio β€” make a RADIO socket. Default action is bind. Draft method, for development use, may change without warning.
  • zsock_new_dish β€” make a DISH socket. Default action is connect. Draft method, for development use, may change without warning.
  • zsock_new_gather β€” make a GATHER socket. Default action is bind. Draft method, for development use, may change without warning.
  • zsock_new_scatter β€” make a SCATTER socket. Default action is connect. Draft method, for development use, may change without warning.
CZMQ_EXPORT zsock_t *
    zsock_new_server (const char *endpoint);

CZMQ_EXPORT zsock_t *
    zsock_new_client (const char *endpoint);

CZMQ_EXPORT zsock_t *
    zsock_new_radio (const char *endpoint);

CZMQ_EXPORT zsock_t *
    zsock_new_dish (const char *endpoint);

CZMQ_EXPORT zsock_t *
    zsock_new_gather (const char *endpoint);

CZMQ_EXPORT zsock_t *
    zsock_new_scatter (const char *endpoint);
  • zsock_new_dgram β€” make a DGRAM (UDP) socket. Default action is bind. The endpoint is a string made of a 'transport' :// followed by an 'address'. Since this is a UDP socket, the 'transport' has to be udp. The 'address' says which ip address and port to bind to. Example: udp://127.0.0.1:1234. πŸ“Œ Note: to send to an endpoint over UDP you have to send a message with the destination endpoint address as a first message! Draft method, for development use, may change without warning.
CZMQ_EXPORT zsock_t *
    zsock_new_dgram (const char *endpoint);

Draft routing IDs and groups πŸŽ€

  • zsock_routing_id β€” returns the socket routing ID, if it has one. Gives you 0 if the socket isn't a ZMQ_SERVER, or if no request has already been received on it. Draft method, for development use, may change without warning.
  • zsock_set_routing_id β€” sets the routing ID on the socket. The socket MUST be of type ZMQ_SERVER. This gets used when sending messages on the socket through the zsock API. Draft method, for development use, may change without warning.
  • zsock_join β€” join a group for the RADIO-DISH pattern. Call it only on ZMQ_DISH. Returns 0 if OK, -1 if it failed. Draft method, for development use, may change without warning.
  • zsock_leave β€” leave a group for the RADIO-DISH pattern. Call it only on ZMQ_DISH. Returns 0 if OK, -1 if it failed. Draft method, for development use, may change without warning.
  • zsock_has_in β€” check whether the socket has a message available to read. Returns a bool. Draft method, for development use, may change without warning.
CZMQ_EXPORT uint32_t
    zsock_routing_id (zsock_t *self);

CZMQ_EXPORT void
    zsock_set_routing_id (zsock_t *self, uint32_t routing_id);

CZMQ_EXPORT int
    zsock_join (void *self, const char *group);

CZMQ_EXPORT int
    zsock_leave (void *self, const char *group);

CZMQ_EXPORT bool
    zsock_has_in (void *self);
#endif // CZMQ_BUILD_DRAFT_API
πŸ“ Heads up, the manpage literally says: Please add '@interface' section in './../src/zsock.c'. So that's a to-do for whoever maintains this thing πŸ™ˆ

πŸ’– DESCRIPTION πŸ’–

Okay so the whole glow-up here: the zsock class wraps the libzmq socket handle (which is a void *) inside a proper structure that actually follows the CLASS rules for construction and destruction. Main character energy only 🌟

Some zsock methods take a void * "polymorphic" reference. That thing can be a zsock_t, or a zactor_t reference, or a plain libzmq void *. It just works, iykyk.

πŸ“ And also literally in the manpage: Please add @discuss section in ./../src/zsock.c.

🌈 EXAMPLE 🌈

From zsock_test method. Strap in, bestie, it's a whole journey ✨

zsock_t *writer = zsock_new (ZMQ_PUSH);
assert (writer);
int port = zsock_bind (writer, "tcp://127.0.0.1:*");
assert (port != -1);
assert (zsock_resolve (writer) != writer);
assert (streq (zsock_type_str (writer), "PUSH"));

int rc;
#if (ZMQ_VERSION >= ZMQ_MAKE_VERSION (3, 2, 0))
//  Check unbind
rc = zsock_unbind (writer, "tcp://127.0.0.1:%d", port);
assert (rc == 0);

//  In some cases and especially when running under Valgrind, doing
//  a bind immediately after an unbind causes an EADDRINUSE error.
//  Even a short sleep allows the OS to release the port for reuse.
zclock_sleep (100);

//  Bind again
rc = zsock_bind (writer, "tcp://127.0.0.1:%d", port);
assert (rc == port);
char endpoint [40];
sprintf (endpoint, "tcp://127.0.0.1:%d", port);
assert (streq (zsock_endpoint (writer), endpoint));
#endif

zsock_t *reader = zsock_new (ZMQ_PULL);
assert (reader);
rc = zsock_connect (reader, "tcp://127.0.0.1:%d", port);
assert (rc != -1);
assert (zsock_resolve (reader) != reader);
assert (streq (zsock_type_str (reader), "PULL"));

//  Basic Hello, World
zstr_send (writer, "Hello, World");
zmsg_t *msg = zmsg_recv (reader);
assert (msg);
char *string = zmsg_popstr (msg);
assert (streq (string, "Hello, World"));
freen (string);
zmsg_destroy (&msg);

//  Test resolve libzmq socket
#if (ZMQ_VERSION >= ZMQ_MAKE_VERSION (3, 2, 0))
void *zmq_ctx = zmq_ctx_new ();
#else
void *zmq_ctx = zmq_ctx_new (1);
#endif
assert (zmq_ctx);
void *zmq_sock = zmq_socket (zmq_ctx, ZMQ_PUB);
assert (zmq_sock);
assert (zsock_resolve (zmq_sock) == zmq_sock);
zmq_close (zmq_sock);
zmq_ctx_term (zmq_ctx);

//  Test resolve zsock
zsock_t *resolve = zsock_new_pub("@tcp://127.0.0.1:*");
assert (resolve);
assert (zsock_resolve (resolve) == resolve->handle);
zsock_destroy (&resolve);

//  Test resolve FD
SOCKET fd = zsock_fd (reader);
assert (zsock_resolve ((void *) &fd) == NULL);

//  Test binding to ephemeral ports, sequential and random
port = zsock_bind (writer, "tcp://127.0.0.1:*");
assert (port >= DYNAMIC_FIRST && port <= DYNAMIC_LAST);
port = zsock_bind (writer, "tcp://127.0.0.1:*[50000-]");
assert (port >= 50000 && port <= DYNAMIC_LAST);
port = zsock_bind (writer, "tcp://127.0.0.1:*[-50001]");
assert (port >= DYNAMIC_FIRST && port <= 50001);
port = zsock_bind (writer, "tcp://127.0.0.1:*[60000-60500]");
assert (port >= 60000 && port <= 60500);

port = zsock_bind (writer, "tcp://127.0.0.1:!");
assert (port >= DYNAMIC_FIRST && port <= DYNAMIC_LAST);
port = zsock_bind (writer, "tcp://127.0.0.1:![50000-]");
assert (port >= 50000 && port <= DYNAMIC_LAST);
port = zsock_bind (writer, "tcp://127.0.0.1:![-50001]");
assert (port >= DYNAMIC_FIRST && port <= 50001);
port = zsock_bind (writer, "tcp://127.0.0.1:![60000-60500]");
assert (port >= 60000 && port <= 60500);

//  Test zsock_attach method
zsock_t *dealer = zsock_new (ZMQ_DEALER);
assert (dealer);
rc = zsock_attach (dealer, "@inproc://myendpoint,tcp://127.0.0.1:*,inproc://others", true);
assert (rc == 0);
rc = zsock_attach (dealer, "", false);
assert (rc == 0);
rc = zsock_attach (dealer, NULL, true);
assert (rc == 0);
rc = zsock_attach (dealer, ">a,@b, c,, ", false);
assert (rc == -1);
zsock_destroy (&dealer);

//  Test zsock_endpoint method
rc = zsock_bind (writer, "inproc://test.%s", "writer");
assert (rc == 0);
assert (streq (zsock_endpoint (writer), "inproc://test.writer"));

//  Test error state when connecting to an invalid socket type
//  ('txp://' instead of 'tcp://', typo intentional)
rc = zsock_connect (reader, "txp://127.0.0.1:5560");
assert (rc == -1);

//  Test signal/wait methods
rc = zsock_signal (writer, 123);
assert (rc == 0);
rc = zsock_wait (reader);
assert (rc == 123);

//  Test zsock_send/recv pictures
uint8_t  number1 = 123;
uint16_t number2 = 123 * 123;
uint32_t number4 = 123 * 123;
number4 *= 123;
uint32_t number4_MAX = UINT32_MAX;
uint64_t number8 = 123 * 123;
number8 *= 123;
number8 *= 123;
uint64_t number8_MAX = UINT64_MAX;

okay the example is literally still going, hold that thought 🫢

...and now we're building the whole little cast of characters, bestie. Every type zsock_recv can hand you gets its own lil cameo here, so watch the glow-up: πŸ’…

           zchunk_t *chunk = zchunk_new ("HELLO", 5);
           assert (chunk);
           zframe_t *frame = zframe_new ("WORLD", 5);
           assert (frame);
           zhashx_t *hash = zhashx_new ();
           assert (hash);
           #ifdef CZMQ_BUILD_DRAFT_API
           zlistx_t *list = zlistx_new ();
           assert (list);
           #endif
           zuuid_t *uuid = zuuid_new ();
           assert (uuid);
           zhashx_set_destructor (hash, (zhashx_destructor_fn *) zstr_free);
           zhashx_set_duplicator (hash, (zhashx_duplicator_fn *) strdup);
           zhashx_insert (hash, "1", "value A");
           zhashx_insert (hash, "2", "value B");
           #ifdef CZMQ_BUILD_DRAFT_API
           zlistx_set_destructor (list, (zlistx_destructor_fn *) zstr_free);
           zlistx_set_duplicator (list, (zlistx_duplicator_fn *) strdup);
           zlistx_add_end (list, "1");
           zlistx_add_end (list, "2");
           #endif
           char *original = "pointer";

Not the assert after literally every single constructor, it's giving paranoid queen and honestly? iconic. If anything fails we find out immediately, no gaslighting ourselves later. 🌸


πŸ¦‹ the big send: zsock_recv into each supported type

Note the #ifdef CZMQ_BUILD_DRAFT_API splits β€” draft API means the format string gets extra letters (l and p) and extra arguments. No cap, the picture string is different depending on the build:

           //  Test zsock_recv into each supported type
           #ifdef CZMQ_BUILD_DRAFT_API
           zsock_send (writer, "i124488zsbcfUhlp",
           #else
           zsock_send (writer, "i124488zsbcfUhp",
           #endif
                       -12345, number1, number2, number4, number4_MAX,
                       number8, number8_MAX,
                       "This is a string", "ABCDE", 5,
           #ifdef CZMQ_BUILD_DRAFT_API
                       chunk, frame, uuid, hash, list, original);
           #else
                       chunk, frame, uuid, hash, original);
           #endif
           char *uuid_str = strdup (zuuid_str (uuid));
           zchunk_destroy (&chunk);
           zframe_destroy (&frame);
           zuuid_destroy (&uuid);
           zhashx_destroy (&hash);
           #ifdef CZMQ_BUILD_DRAFT_API
           zlistx_destroy (&list);
           #endif

STOP. Bestie, look at char *uuid_str = strdup (zuuid_str (uuid)); β€” we save the uuid's string before we nuke the uuid itself, because we're gonna compare it on the other side. That's the kind of 4D chess move that makes you feel like the main character. πŸ‘‘

Then everything gets _destroy'd so we start the receive side with a clean slate. Detach, hydrate, slay. ✨


πŸ’œ the receive side + the vibe check (asserts)

Everything gets zeroed out first β€” number8_MAX = number8 = number4_MAX = number4 = number2 = number1 = 0ULL; β€” so if zsock_recv doesn't actually write anything, the asserts will catch it. Trust issues? no, healthy skepticism. 🧚

           int integer;
           byte *data;
           size_t size;
           char *pointer;
           number8_MAX = number8 = number4_MAX = number4 = number2 = number1 = 0ULL;
           #ifdef CZMQ_BUILD_DRAFT_API
           rc = zsock_recv (reader, "i124488zsbcfUhlp",
           #else
           rc = zsock_recv (reader, "i124488zsbcfUhp",
           #endif
                            &integer, &number1, &number2, &number4, &number4_MAX,
                            &number8, &number8_MAX, &string, &data, &size, &chunk,
           #ifdef CZMQ_BUILD_DRAFT_API
                            &frame, &uuid, &hash, &list, &pointer);
           #else
                            &frame, &uuid, &hash, &pointer);
           #endif
           assert (rc == 0);
           assert (integer == -12345);
           assert (number1 == 123);
           assert (number2 == 123 * 123);
           assert (number4 == 123 * 123 * 123);
           assert (number4_MAX == UINT32_MAX);
           assert (number8 == 123 * 123 * 123 * 123);
           assert (number8_MAX == UINT64_MAX);
           assert (streq (string, "This is a string"));
           assert (memcmp (data, "ABCDE", 5) == 0);
           assert (size == 5);
           assert (memcmp (zchunk_data (chunk), "HELLO", 5) == 0);
           assert (zchunk_size (chunk) == 5);
           assert (streq (uuid_str, zuuid_str (uuid)));
           assert (memcmp (zframe_data (frame), "WORLD", 5) == 0);
           assert (zframe_size (frame) == 5);
           char *value = (char *) zhashx_lookup (hash, "1");
           assert (streq (value, "value A"));
           value = (char *) zhashx_lookup (hash, "2");
           assert (streq (value, "value B"));
           #ifdef CZMQ_BUILD_DRAFT_API
           value = (char *) zlistx_first (list);
           assert (streq (value, "1"));
           value = (char *) zlistx_last (list);
           assert (streq (value, "2"));
           #endif
           assert (original == pointer);
           freen (string);
           freen (data);
           freen (uuid_str);
           zframe_destroy (&frame);
           zchunk_destroy (&chunk);
           zhashx_destroy (&hash);
           #ifdef CZMQ_BUILD_DRAFT_API
           zlistx_destroy (&list);
           #endif
           zuuid_destroy (&uuid);

The way number4_MAX == UINT32_MAX and number8_MAX == UINT64_MAX are just flexing that the max values survive the round trip intact. Fr fr. And assert (original == pointer); β€” the pointer that comes out is literally the same pointer that went in. Not a copy. The SAME ONE. It's giving soulmate energy. πŸ’–

Also peep the freen calls and all the _destroys at the bottom β€” clean up after yourself, bestie, nobody wants a memory leak haunting the group chat. πŸ’€


πŸŽ€ the short message (aka the graceful L)

This one's lowkey clever: you can send a status code and nothing else, and the receiver gets that code with NULL/zero for everything it asked for:

           //  Test zsock_recv of short message; this lets us return a failure
           //  with a status code and then nothing else; the receiver will get
           //  the status code and NULL/zero for all other values
           zsock_send (writer, "i", -1);
           zsock_recv (reader, "izsbcfp",
               &integer, &string, &data, &size, &chunk, &frame, &pointer);
           assert (integer == -1);
           assert (string == NULL);
           assert (data == NULL);
           assert (size == 0);
           assert (chunk == NULL);
           assert (frame == NULL);
           assert (pointer == NULL);

So -1 arrives, and every single other thing is NULL or 0. No drama, no half-filled garbage. 🫢


🌈 zmsg round trip (the szm moment)

           msg = zmsg_new ();
           zmsg_addstr (msg, "frame 1");
           zmsg_addstr (msg, "frame 2");
           zsock_send (writer, "szm", "header", msg);
           zmsg_destroy (&msg);

           zsock_recv (reader, "szm", &string, &msg);

           assert (streq ("header", string));
           assert (zmsg_size (msg) == 2);
           assert (zframe_streq (zmsg_first (msg), "frame 1"));
           assert (zframe_streq (zmsg_next (msg), "frame 2"));
           zstr_free (&string);
           zmsg_destroy (&msg);

A whole multipart zmsg goes over the wire and comes back with both frames still in order β€” zmsg_first gives you "frame 1", zmsg_next gives you "frame 2". Two-frame message, fully intact, no notes. 🌟


πŸ“ zsock_recv with null arguments

Real ones know: you don't have to receive everything. Pass NULL for the stuff you don't care about:

           //  Test zsock_recv with null arguments
           chunk = zchunk_new ("HELLO", 5);
           assert (chunk);
           frame = zframe_new ("WORLD", 5);
           assert (frame);
           zsock_send (writer, "izsbcfp",
                       -12345, "This is a string", "ABCDE", 5, chunk, frame, original);
           zframe_destroy (&frame);
           zchunk_destroy (&chunk);
           zsock_recv (reader, "izsbcfp", &integer, NULL, NULL, NULL, &chunk, NULL, NULL);
           assert (integer == -12345);
           assert (memcmp (zchunk_data (chunk), "HELLO", 5) == 0);
           assert (zchunk_size (chunk) == 5);
           zchunk_destroy (&chunk);

We only wanted the integer and the chunk, so everything else is a big ol' NULL. The chunk still arrives saying "HELLO", size 5. Selective listening, but make it C. πŸ’…


⭐ zsock_bsend / zsock_brecv β€” the binary encoding era

New format string, new letters: "1248sSpcfm". And here's the glow-up: strings come back as freshly allocated (zstr_free them), the pointer is still identical, and zmsg is still in the picture. πŸ”₯

           //  Test zsock_bsend/brecv pictures with binary encoding
           frame = zframe_new ("Hello", 5);
           chunk = zchunk_new ("World", 5);

           msg = zmsg_new ();
           zmsg_addstr (msg, "Hello");
           zmsg_addstr (msg, "World");

           zsock_bsend (writer, "1248sSpcfm",
                        number1, number2, number4, number8,
                        "Hello, World",
                        "Goodbye cruel World!",
                        original,
                        chunk, frame, msg);
           zchunk_destroy (&chunk);
           zframe_destroy (&frame);
           zmsg_destroy (&msg);

           number8 = number4 = number2 = number1 = 0;
           char *longstr;
           zsock_brecv (reader, "1248sSpcfm",
                        &number1, &number2, &number4, &number8,
                        &string, &longstr,
                        &pointer,
                        &chunk, &frame, &msg);
           assert (number1 == 123);
           assert (number2 == 123 * 123);
           assert (number4 == 123 * 123 * 123);
           assert (number8 == 123 * 123 * 123 * 123);
           assert (streq (string, "Hello, World"));
           assert (streq (longstr, "Goodbye cruel World!"));
           assert (pointer == original);
           zstr_free (&longstr);
           zchunk_destroy (&chunk);
           zframe_destroy (&frame);
           zmsg_destroy (&msg);

"Hello, World" and "Goodbye cruel World!" both survive verbatim, pointer == original again (it's always that pointer, bestie, it's endgame πŸ’–), and we zstr_free (&longstr) because we own it now. Responsible queen behavior. πŸ‘‘


πŸ’€ ZMQ_SERVER / ZMQ_CLIENT β€” the two-way street

If the build has ZMQ_SERVER, we spin up a server and a client, bind, connect, and send the same picture both directions. Note the zsock_routing_id asserts β€” the server's is truthy, the client's is 0:

           #ifdef ZMQ_SERVER

           //  Test zsock_bsend/brecv pictures with binary encoding on SERVER and CLIENT sockets
           zsock_t *server = zsock_new (ZMQ_SERVER);
           assert (server);
           port = zsock_bind (server, "tcp://127.0.0.1:*");
           assert (port != -1);
           zsock_t* client = zsock_new (ZMQ_CLIENT);
           assert (client);
           rc = zsock_connect (client, "tcp://127.0.0.1:%d", port);
           assert (rc != -1);

           //  From client to server
           chunk = zchunk_new ("World", 5);
           zsock_bsend (client, "1248sSpc",
                        number1, number2, number4, number8,
                        "Hello, World",
                        "Goodbye cruel World!",
                        original,
                        chunk);
           zchunk_destroy (&chunk);

           number8 = number4 = number2 = number1 = 0;
           zsock_brecv (server, "1248sSpc",
                        &number1, &number2, &number4, &number8,
                        &string, &longstr,
                        &pointer,
                        &chunk);
           assert (number1 == 123);
           assert (number2 == 123 * 123);
           assert (number4 == 123 * 123 * 123);
           assert (number8 == 123 * 123 * 123 * 123);
           assert (streq (string, "Hello, World"));
           assert (streq (longstr, "Goodbye cruel World!"));
           assert (pointer == original);
           assert (zsock_routing_id (server));
           zstr_free (&longstr);
           zchunk_destroy (&chunk);

           //  From server to client
           chunk = zchunk_new ("World", 5);
           zsock_bsend (server, "1248sSpc",
                        number1, number2, number4, number8,
                        "Hello, World",
                        "Goodbye cruel World!",
                        original,
                        chunk);
           zchunk_destroy (&chunk);

           number8 = number4 = number2 = number1 = 0;
           zsock_brecv (client, "1248sSpc",
                        &number1, &number2, &number4, &number8,
                        &string, &longstr,
                        &pointer,
                        &chunk);
           assert (number1 == 123);
           assert (number2 == 123 * 123);
           assert (number4 == 123 * 123 * 123);
           assert (number8 == 123 * 123 * 123 * 123);
           assert (streq (string, "Hello, World"));
           assert (streq (longstr, "Goodbye cruel World!"));
           assert (pointer == original);
           assert (zsock_routing_id (client) == 0);
           zstr_free (&longstr);
           zchunk_destroy (&chunk);

           zsock_destroy (&client);
           zsock_destroy (&server);

And if ZMQ_SERVER isn't there? Bestie, we test the failure path. zsock_new_server and zsock_new_client both hand back NULL and set errno to ENOTSUP:

           #else
           errno = 0;
           zsock_t* server = zsock_new_server (NULL);
           assert(server == NULL);
           assert(errno == ENOTSUP);

           errno = 0;
           zsock_t* client = zsock_new_client (NULL);
           assert(client == NULL);
           assert(errno == ENOTSUP);
           #endif

errno = 0; before each check because you gotta reset the vibe before you read it. 🧚


πŸŽ€ ZMQ_SCATTER / ZMQ_GATHER

Scatter sends, gather receives β€” one "HELLO" travels the inproc://test-gather-scatter pipe:

           #ifdef ZMQ_SCATTER

           zsock_t* gather = zsock_new_gather ("inproc://test-gather-scatter");
           assert (gather);
           zsock_t* scatter = zsock_new_scatter ("inproc://test-gather-scatter");
           assert (scatter);

           rc = zstr_send (scatter, "HELLO");
           assert (rc == 0);

           char* message;
           message = zstr_recv (gather);
           assert (streq(message, "HELLO"));
           zstr_free (&message);

           zsock_destroy (&gather);
           zsock_destroy (&scatter);
           #else
           errno = 0;
           zsock_t* scatter = zsock_new_scatter (NULL);
           assert(scatter == NULL);
           assert(errno == ENOTSUP);

           errno = 0;
           zsock_t* gather = zsock_new_gather (NULL);
           assert(gather == NULL);
           assert(errno == ENOTSUP);
           #endif

Same deal without ZMQ_SCATTER: both constructors return NULL, both set errno to ENOTSUP. Equal opportunity rejection. πŸ’…


🌸 no ZMQ_RADIO? still gotta test it

And here's the last lil block of this part β€” radio and dish, both expected to bounce with ENOTSUP when ZMQ_RADIO isn't defined:

           #ifndef ZMQ_RADIO
           errno = 0;
           zsock_t* radio = zsock_new_radio (NULL);
           assert(radio == NULL);
           assert(errno == ENOTSUP);

           errno = 0;
           zsock_t* dish = zsock_new_dish (NULL);
           assert(dish == NULL);
           assert(errno == ENOTSUP);

Two errno = 0; resets, two NULL returns, two ENOTSUPs. Consistent. Obsessed. ✨

           errno = 0;
           zsock_t* sock = zsock_new_req (NULL); // any supported socket type
           rc = zsock_join (sock, "group1");
           assert(rc == -1);
           assert(errno == ENOTSUP);
           errno = 0;
           rc = zsock_leave (sock, "group1");
           assert(rc == -1);
           assert(errno == ENOTSUP);
           zsock_destroy (&sock);
           #endif

           //  Check that we can send a zproto format message
           zsock_bsend (writer, "1111sS4", 0xAA, 0xA0, 0x02, 0x01, "key", "value", 1234);
           zgossip_msg_t *gossip = zgossip_msg_new ();
           zgossip_msg_recv (gossip, reader);
           assert (zgossip_msg_id (gossip) == ZGOSSIP_MSG_PUBLISH);
           zgossip_msg_destroy (&gossip);

           zsock_destroy (&reader);
           zsock_destroy (&writer);

           #ifdef ZMQ_DGRAM
           // ZMQ_DGRAM ipv4 unicast test
           zsock_t* dgramr = zsock_new_dgram ("udp://*:7777");
           assert (dgramr);
           assert ( streq( "DGRAM", zsys_sockname(ZMQ_DGRAM)) );
           //zsock_t* dgrams = zsock_new_dgram ("udp://*:*");
           zsock_t* dgrams = zsock_new (ZMQ_DGRAM);
           zsock_bind (dgrams, "udp://127.0.0.1:7778" );

           assert (dgrams);
           // perhaps sleep a little for sockets to setup?

           rc = zstr_sendm( dgrams, "127.0.0.1:7777" );
           assert (rc == 0);
           rc = zstr_send (dgrams, "HELLO");
           assert (rc == 0);

           char *dmessage, *addr;

           zmsg_t *dmsg = zmsg_recv( dgramr );
           assert (dmsg);
           addr = zmsg_popstr (dmsg);
           dmessage = zmsg_popstr (dmsg);
           assert (streq(dmessage, "HELLO"));
           zmsg_destroy ( &dmsg );
           zsock_destroy (&dgrams);
           zsock_destroy (&dgramr);
           zstr_free (&dmessage);
           zstr_free (&addr);
           zstr_free (&message);

           // ZMQ_DGRAM ipv4 multicast test
           zsock_t* mdgramr = zsock_new_dgram ("udp://225.25.25.25:7777");
           assert (mdgramr);
           zsock_t* mdgrams = zsock_new_dgram ("udp://*:*");
           assert (mdgrams);

           rc = zstr_sendm( mdgrams, "225.25.25.25:7777" );
           assert (rc == 0);
           rc = zstr_send (mdgrams, "HELLO");
           assert (rc == 0);

           char *mdmessage, *maddr;

           zmsg_t *mdmsg = zmsg_recv( mdgramr );
           assert (mdmsg);
           maddr = zmsg_popstr (mdmsg);
           mdmessage = zmsg_popstr (mdmsg);
           assert (streq(mdmessage, "HELLO"));
           zmsg_destroy ( &mdmsg );
           zsock_destroy (&mdgrams);
           zsock_destroy (&mdgramr);
           zstr_free (&mdmessage);
           zstr_free (&maddr);
           zstr_free (&mdmessage);

           //    // ipv6 (not supported yet)
           //    zsys_set_ipv6(1);
           //    zsock_t* dgramr6 = zsock_new_dgram ("udp://*:7777");
           //    assert (dgramr6);
           //    zsock_t* dgrams6 = zsock_new_dgram ("udp://*:*");
           //    assert (dgrams6);
           //    // perhaps sleep a little for sockets to setup?
           //    zclock_sleep(100);

           //    rc = zstr_sendm( dgrams6, "::1:7777" );
           //    assert (rc == 0);
           //    rc = zstr_send (dgrams6, "HELLO");
           //    assert (rc == 0);

           //    char *dmessage6, *addr6;
           //    zmsg_t *dmsg6 = zmsg_recv( dgramr6 );
           //    assert (dmsg6);
           //    addr6 = zmsg_popstr (dmsg6);
           //    dmessage6 = zmsg_popstr(dmsg6);
           //    assert (streq(dmessage6, "HELLO"));
           //    zmsg_destroy( &dmsg6 );
           //    zsock_destroy (&dgrams6);
           //    zsock_destroy (&dgramr6);

           //    zstr_free (&dmessage6);
           //    zstr_free (&addr6);
           //    zstr_free (&dmessage6);
           #endif

πŸ‘‘ AUTHORS πŸ’–

The czmq manual was written by the authors in the AUTHORS file. That's it, that's the whole thing β€” the whole squad showed up and wrote it together, and their names live in that file. Slay. ✨


🌈 RESOURCES πŸ¦‹

Main web site:

Report bugs to the email <zeromq-dev@lists.zeromq.org[1]> πŸ›πŸ’Œ

lowkey the "Main web site" field is sitting there empty in the source, bestie β€” no URL, no nothing, just the label. Not me pointing that out. πŸ™ˆ Anyway, found a bug? Email the list, they're lovely.

Copyright (c) the Contributors as noted in the AUTHORS file. This file is part of CZMQ, the high-level C binding for 0MQ: http://czmq.zeromq.org. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. LICENSE included with the czmq distribution. πŸ“œβœ¨

it's giving legally binding, and we respect it. Read your licenses, bestie, they ate. 🫢

🧚 NOTES ⭐

  1. zeromq-dev@lists.zeromq.org mailto:zeromq-dev@lists.zeromq.org

okay bestie that's the WHOLE page, we did it, every last flag and assert and license clause, nothing skipped, periodt πŸ’–πŸŒΈ

this whole glow-up is brought to you by CZMQ 4.2.1, dated 01/16/2026, and yes it's ZSOCK(3) β€” the manual page, the moment, the icon. go forth and socket responsibly, my love πŸ‘‘πŸ¦‹πŸ’…

πŸ“¦ where this page comes from