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 sam
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
"
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 )
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:
rc = zmq_connect(socket, "tcp://192.168.1.17:5555;192.168.1.1:5555")
In Python, this looks like:
socket = zmq.Context().socket(zmq.SUB)
socket.connect('tcp://192.168.1.17:5555;192.168.1.1:5555')