The Python standard library's socket
.create_connection()
method has a source address option, for controlling which source IP a connection uses.
How do I do the same thing with a Python ZeroMQ socket, given a machine that has multiple addresses?
In this case, I've been using Linux's iproute2 ip addr add
to create the addresses and the ZeroMQ PUB/SUB
socket-archetypes.
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" - aContext( 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:
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, whereasPUB/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.
When trying to
.connect()
to a remote, I found the answer in the protocol documentation, put the source ip before a semicolon in the connect string:In Python, this looks like: