How to control the source IP address of a ZeroMQ packet on a machine with multiple IPs?
Well, ZeroMQ is a bit tricky to read as a socket
-"counterparty" ( it's not )
Why?
Classical socket
is a free-to-harness resource.
ZeroMQ is a rather complex hierarchy of ideas and principles of behaviours ( better - distributed behaviours ), that help design smart distributed computing systems, without touching the low-level ( ZeroMQ well abstracted ) details, that control the actual flow of events in the storms of harsh conditions all distributed computing systems are open to face ( and have to handle at low level accordingly, if the high-level abstractions "promised" by ZeroMQ to keep are to be fulfilled and ease the designers' minds to focus rather on his/her core application part, not re-designing wheels ( with all trials and errors ) on pulling strings on O/S resources and shaking systems services for collecting just a few low-hanging types of fruits ).
For these reasons better straight forget ZeroMQ to be "something-like-socket
"
ZeroMQ hierarchy in less than a five seconds
1:
ZeroMQ promises an easy re-use of a few trivial Scalable Formal Communication Pattern archetypes offering a particular distributed behaviour { PUB/SUB | PUSH/PULL | PAIR/PAIR | XPUB/XSUB | ... | REQ/REP }
.
2:
Except a case of exclusively using just a device-less inproc://
transport-class, in all other cases, ZeroMQ needs one or more instances of a tunable "engine" - a Context( nIOthreads = N )
, N >= 1
.
3:
Having this, any ( future socket ) Access Point could get instantiated, bearing a behavioural archetype since the very moment of birth:
aSubscribeCHANNEL = aLocalCONTEXT.socket( zmq.SUB ) # this is NOT a <SOCKET>
# ^^^^^^__________________ even it was typed in
4:
Having an "Access Point" instance ready "inside" the local "engine", one can lock-in its materialisation in the external-reality, using one or more ( yes, more ... WOW! Meaning more incoming pulling-strings into / whistles blowing out from a single Access Point "behaviour-node" ) calls to either of these methods:
.bind(
<transport-class>://<a-class-specific-address>
)
or
.connect(
<transport-class>://<a-class-specific-address>
)
5:
If and only if a .bind()
-RTO-ready Access Point A "gets visited" by a first live .connect()
-RTO-ready Access Point B, having any matching behaviour pairing, the ZeroMQ-messaging/signalling archetype gets live ( naming it also a socket was probably used for historical reasons, to ease an explanation in times )
( PUB/PUB
will never fit, for obvious reasons, whereas PUB/SUB
and many other behaviour-archetype pairs will and do lovely match and form the mutually-"compatible"-behaviours that will finally go live and stay so )
So,
how do I do the same thing with a Python ZeroMQ socket,
given a machine that has multiple addresses?
Simply use the fully qualified specification in a call to
.bind(
"{ tcp | pgm | epgm }://<ip>:<port#>"
)
method and you are done.
That easy.
Cool, isn't it?
Many further pleasant surprises under the hood of performance tuning, latency shaving and security tweaking.