NN_SENDMSG(3)

πŸ“¦
version 1.2.2 Β· 5 versions
, in fedora 44

πŸ’Œ NN_SENDMSG(3) β€” the nanomsg glow-up send πŸ’…

okay bestie, welcome to nn_sendmsg from nanomsg 1.2.2 β€” it's the fine-grained, main-character alternative to nn_send, and honestly? it's giving control freak in the best way possible. πŸŽ€


✨ NAME ✨

nn_sendmsg β€” the fine-grained alternative to nn_send, no cap πŸ’–


πŸ¦‹ SYNOPSIS πŸ¦‹

#include <nanomsg/nn.h>

int nn_sendmsg (int s, const struct nn_msghdr *msghdr, int flags);

🌸 DESCRIPTION 🌸

So what it does: it sends the data that msghdr is pointing at over to socket s, plus any extra control data you wanna bring along for the ride. ✨

🚨 real talk: nullify that msghdr structure before you use it. like, memset it to zero first. do not skip this.

The nn_msghdr structure contains at least these members:

struct nn_iovec *msg_iov;
int msg_iovlen;
void *msg_control;
size_t msg_controllen;
  • msg_iov β€” points to a scatter array of buffers to send 🌈
  • msg_iovlen β€” says how big that array is
  • msg_control β€” points to the buffer holding the control information that gets associated with the message being sent πŸŽ€
  • msg_controllen β€” the length of that buffer

If there's literally no control information to send, set msg_control to NULL. periodt. And for the whole deep-dive on how to actually set control data, go read the nn_cmsg(3) man page, bestie. πŸ’…

Now the nn_iovec structure defines one single element in the scatter array (aka one buffer you're sending to the socket), and it's got these members:

void *iov_base;
size_t iov_len;

Okay so alternative route, and this one is lowkey iconic: if you wanna send a buffer that was allocated by nn_allocmsg(3), you set iov_base to point to the pointer to the buffer and iov_len to the NN_MSG constant. 🫢

πŸ’€ heads up: in that case, a successful call to nn_sendmsg will deallocate the buffer for you. if you try to deallocate it again afterwards, that's undefined behaviour. also, when you're doing this, the scatter array inside the nn_msghdr structure can contain only one element. one. that's it.

Which of the peers the message actually gets sent to? that's determined by the particular socket type, so iykyk 🧚

The flags argument is a combo of the flags defined below:

  • NN_DONTWAIT β€” says the operation should be performed in non-blocking mode. if the message can't be sent straight away, the function fails and sets errno to EAGAIN. no waiting, we're busy. ⭐

πŸ‘‘ RETURN VALUE πŸ‘‘

If it works? you get the number of bytes in the message back. slay. πŸŽ‰

Otherwise you get -1, and errno is set to one of the values down below. 😭


πŸ’€ ERRORS πŸ’€

  • EINVAL β€” either msghdr is NULL, or there are multiple scatter buffers but the length is set to NN_MSG for one of them, or the sum of the iov_len values for the scatter buffers overflows size_t. these are early checks, and no pre-allocated message gets freed in this case.
  • EMSGSIZE β€” msghdrβ†’msg_iovlen is negative. also an early check, and again, no pre-allocated message gets freed in this case.
  • EFAULT β€” the pointer you supplied for the pre-allocated message buffer or the scatter buffer is NULL, or the length for the scatter buffer is 0. empty, bestie, we can't work with that. πŸ™ˆ
  • EBADF β€” the socket you provided is invalid.
  • ENOTSUP β€” this socket type just doesn't support this operation. not our vibe, sorry.
  • EFSM β€” the operation can't be performed on this socket right now because the socket isn't in the appropriate state. this one can happen with socket types that switch between several states. πŸ¦‹
  • EAGAIN β€” non-blocking mode was requested and the message can't be sent at the moment.
  • EINTR β€” the operation got interrupted by delivery of a signal before the message was sent. rude tbh.
  • ETIMEDOUT β€” individual socket types may define their own specific timeouts, and if such a timeout is hit, this error gets returned. ⏰
  • ETERM β€” the library is terminating. goodbye era. πŸ’œ

🌈 EXAMPLE 🌈

Usage of multiple scatter buffers:

struct nn_msghdr hdr;
struct nn_iovec iov [2];

iov [0].iov_base = "Hello";
iov [0].iov_len = 5;
iov [1].iov_base = "World";
iov [1].iov_len = 5;
memset (&hdr, 0, sizeof (hdr));
hdr.msg_iov = iov;
hdr.msg_iovlen = 2;
nn_sendmsg (s, &hdr, 0);

Usage of a single message:

void *msg;
struct nn_msghdr hdr;
struct nn_iovec iov;

msg = nn_allocmsg(12, 0);
strcpy(msg, "Hello World");
iov.iov_base = &msg;
iov.iov_len = NN_MSG;
memset (&hdr, 0, sizeof (hdr));
hdr.msg_iov = &iov;
hdr.msg_iovlen = 1;
nn_sendmsg (s, &hdr, 0);

πŸŽ€ SEE ALSO πŸŽ€

nn_send(3) nn_recvmsg(3) nn_allocmsg(3) nn_freemsg(3) nn_cmsg(3) nanomsg(7)


🫢 AUTHORS 🫢

Martin Sustrik <sustrik@250bpm.com>


and that's the whole page, bestie β€” this one's from nanomsg 1.2.2, dated 2026-01-16, and it was literally iconic of you to read all the way to the end. go send some messages. mwah. πŸ’–βœ¨

πŸ“¦ where this page comes from