could run that client many times in parallel
Well, actually could not.
This statement, while believed to have been presented in a good will to explain something, may and actually is a lot damaging one's Computer Science general perspective how things work as it is awfully misleading.
A localhost O/S may run a ZeroMQ based client-code many times concurrently [True]
distributed-system can run a ZeroMQ based client-code many times concurrently [True]
[any-ecosystem] can run a ZeroMQ based client-code many time in parallel [False]
None can and never will. Neither a Cray's excellent parallel processing language chapel can make it happen, as the ZeroMQ is principally an asynchronous, "just"-[CONCURRENT]
process-scheduling ecosystem, where each main engine, operated inside each of the Context()
-instance(s), operating internal pool of 1+ IO-threads ( well, actually 0+, if purists would claim a special case :o) ), is known to be by-design asynchronous and independent to external events flow, so indeed never a true-[PARALLEL]
process scheduling may appear here.
One may enjoy first a short read into an introductory view, about the main conceptual elements as briefed in [ ZeroMQ hierarchy in less than a five seconds ] Section, as it will help us speak the same language in deeper views into the possibilities of the ZeroMQ-based distributed-system domain.
How to use the server-client, and client-server communication at the same time on one PC?
Easy :
One PC can launch first a python interpreter, running the server.py
-side code. Next one can launch a second python interpreter ( be it in another linux terminal, or windows window or cmd
-shell ) and run the client.py
-side code. This will work as charm.
If interested in details, beware that REQ/REP
Scalable Formal Communication Archetype Pattern is principally dangerous for any production-grade professional code, as it can ( and will ) easily turn a distributed-system into a principally un-avoidable, un-salvageable mutual dead-lock ( simply the distributed pair of FSA:FSA can fall into a dead-lock state, from which neither side can rescue and continue the flow of mutual co-operations )
Do we need to make threads for achieving this ?
Well, there are actually many threads already operating "inside", if no others, there are a few of threads already inside each python + ZeroMQ Context()
composition.
If you meant to instruct python code to start using more threads, there ought be more details about such intention, before one can help in such decision dilemma(s). There is also a principal drawback of using threads - the known python GIL-locking makes actually any such attempt into a pure-[SERIAL]
, yes, step-by-step sequentially ordered code-execution ( as this helps keep the the GIL-protector's effect onto data monopolistic access ( [SERIAL]
-ised code-execution never goes into a colliding case of non-atomic write(s), the less a race-condition, as the GIL-stepping actually makes each and every operation an atomic step -- sure, at a cost of chopped, [SERIAL] GIL-stepping through all the thread-pool executed code-execution graphs. Safe? Well, yes, but slower than necessary ).
The best next step ?
If indeed serious and keen to dive into a [distributed-system] design, the best next step is to read a fabulous Pieter HINTJENS' book [Code Connected, Volume 1] ( pdf online ), where all time and efforts are well rewarded by getting a well crafted practical views and lots of pieces of experience, so needed to squeeze as much from the ZeroMQ as it can and will deliver to one's further smart designs.
Stay tuned, this is a step towards the correct direction.