ZMQ_TCP(7)

πŸ’– zmq_tcp β€” the 0MQ unicast transport using TCP πŸ’–

okay bestie, this is page zmq_tcp(7) from the 0MQ Manual, and it's literally the glow-up guide to talking over TCP with ZeroMQ. no cap, let's go πŸ¦‹


✨ NAME ✨

zmq_tcp β€” the 0MQ unicast transport that runs on TCP, periodt.


🌸 SYNOPSIS 🌸

TCP is everywhere. it's reliable, it's unicast, it's the moment. when you're wiring up distributed apps over a network with 0MQ, TCP is highkey gonna be your first pick. it's giving default main character energy πŸ‘‘


πŸŽ€ ADDRESSING πŸŽ€

so a 0MQ endpoint is just a string: a transport:// followed by an address. the transport bit tells you which underlying protocol you're using, and the address bit is whatever that transport wants you to hand over.

for the TCP transport, the transport is tcp, and the address part works like this ⬇️

πŸ’… Assigning a local address to a socket

when you assign a local address to a socket with zmq_bind() and the tcp transport, the endpoint gets read as an interface, then a colon, then the TCP port number you want.

your interface can be any of these:

  • The wild-card *, which means every available interface. all of them. the whole squad πŸ’–
  • The primary IPv4 or IPv6 address that's assigned to the interface, written in its numeric representation.
  • The non-portable interface name, as defined by your operating system. (iykyk, it's not portable, don't @ me)

and your TCP port number can be:

  • A numeric value β€” usually above 1024 on POSIX systems.
  • The wild-card *, meaning a system-assigned ephemeral port ✨
when you're using ephemeral ports, you should grab the actual assigned port with the ZMQ_LAST_ENDPOINT socket option. peek at zmq_getsockopt(3) for the deets.

πŸ¦‹ Unbinding wild-card address from a socket

if you used a wild-card * endpoint in zmq_bind(), then to unbind it with zmq_unbind() you gotta use the real endpoint you got from the ZMQ_LAST_ENDPOINT socket option. not the wild-card. the actual one. slay 🫢

🌈 Connecting a socket

when you connect a socket to a peer address with zmq_connect() and the tcp transport, the endpoint is read as a peer address, then a colon, then the TCP port number to use. you can optionally specify a source_endpoint, which gets used as the source address for your connection β€” that's tcp://source_endpoint;'endpoint', and you can look at the interface description above for the details ✨

a peer address can be either of these:

  • The DNS name of the peer.
  • The IPv4 or IPv6 address of the peer, in its numeric representation.
Note: there's a whole description of the ZeroMQ Message Transport Protocol (ZMTP), which is what the TCP transport uses, over at http://rfc.zeromq.org/spec:23 πŸ“–

πŸ”₯ HWM πŸ”₯

okay so for the TCP transport, the high water mark (HWM) mechanism works together with the TCP socket buffers that the OS handles. depending on your OS and a bunch of other factors, the size of those TCP buffers is gonna be different. and worse β€” the TCP buffers the OS gives you fit a varying number of messages depending on how big the messages are. unlike ZMQ HWM settings, TCP socket buffers are measured in bytes, not messages. πŸ’€

this can lead to some apparently inexplicable behavior. like, say you set ZMQ_SNDHWM to 100 on a socket using the TCP transport and you expect the 101st message to get blocked when the receiver is slow. yeah… that's very unlikely with TCP, because the OS TCP buffers will typically give you enough buffering to send way more than 100 messages. πŸ™ˆ

and ofc, if the receiver is slow, transmitting on a TCP ZMQ socket will eventually trigger the "mute state" of the socket. so just… don't rely on the exact HWM value. fr fr.

obviously the same considerations apply for the receive HWM (check ZMQ_RCVHWM).


⭐ EXAMPLES ⭐

Assigning a local address to a socket.

//  TCP port 5555 on all available interfaces
rc = zmq_bind(socket, "tcp://*:5555");
assert (rc == 0);
//  TCP port 5555 on the local loop-back interface on all platforms
rc = zmq_bind(socket, "tcp://127.0.0.1:5555");
assert (rc == 0);
//  TCP port 5555 on the first Ethernet network interface on Linux
rc = zmq_bind(socket, "tcp://eth0:5555");
assert (rc == 0);

Connecting a socket.

//  Connecting using an IP address
rc = zmq_connect(socket, "tcp://192.168.1.1:5555");
assert (rc == 0);
//  Connecting using a DNS name
rc = zmq_connect(socket, "tcp://server1:5555");
assert (rc == 0);
//  Connecting using a DNS name and bind to eth1
rc = zmq_connect(socket, "tcp://eth1:0;server1:5555");
assert (rc == 0);
//  Connecting using a IP address and bind to an IP address
rc = zmq_connect(socket, "tcp://192.168.1.17:5555;192.168.1.1:5555");
assert (rc == 0);

πŸ‘‘ SEE ALSO πŸ‘‘

zmq_bind(3) zmq_connect(3) zmq_pgm(7) zmq_ipc(7) zmq_inproc(7) zmq_vmci(7) zmq(7)


πŸ’œ AUTHORS πŸ’œ

this page was written by the 0MQ community. wanna make a change? read the 0MQ Contribution Policy at http://www.zeromq.org/docs:contributing β€” the community would literally love that 🫢


and that's the whole page, bestie!! this was 0MQ 4.3.5, dated 10/09/2023, and it's page ZMQ_TCP(7) πŸ’–βœ¨ no cap, you're gonna be a TCP icon now. bye bye πŸŽ€πŸ¦‹

πŸ“¦ where this page comes from