1

I want to make a simple connection between a Python program and a Ruby program using ZeroMQ, I am trying to use a PAIR connection, but I have not been able.

This is my code in python (the server):

import zmq 
import time 

port = "5553" 
context = zmq.Context() 
socket = context.socket(zmq.PAIR) 
socket.bind("tcp://*:%s" % port) 

while True: 
    socket.send(b"Server message to client3") 
    print("Enviado mensaje") 
    time.sleep(1)

It does not display anything until I connect a client.

This is the code in Ruby (the client)

require 'ffi-rzmq'
context = ZMQ::Context.new
subscriber = context.socket ZMQ::PAIR
subscriber.connect "tcp://localhost:5553"
loop do
    address = ''
    subscriber.recv_string address
    puts "[#{address}]"
end

The ruby script just freezes, it does not print anything, and the python script starts printing Enviando mensaje

B.T.W: I am using Python 3.6.9 and Ruby 2.6.5

What is the correct way to connect a zmq PAIR between Ruby and Python?

user3666197
  • 1
  • 6
  • 50
  • 92
Alejo Dev
  • 23
  • 6

1 Answers1

1

Welcome to the Zen of Zero!
In case one has never worked with ZeroMQ,
one may here enjoy to first look at "ZeroMQ Principles in less than Five Seconds" before diving into further details

Q : It does not display anything until I connect a client.

Sure, it does not, your code imperatively asked to block until a PAIR/PAIR delivery channel got happen to become able to deliver a message. As the v4.2+ API defines, the .send()-method will block during all the duration of a "mute state".

When a ZMQ_PAIR socket enters the mute state due to having reached the high water mark for the connected peer, or if no peer is connected, then any zmq_send(3) operations on the socket shall block until the peer becomes available for sending; messages are not discarded.

May try non-blocking mode of sending ( always a sign of a good engineering practice to avoid blocking, the more in ) and better include also <aSocket>.close() and <aContext>.term() as a rule of thumb ( best with explicit .setsockopt( zmq.LINGER, 0 ) ) for avoiding hang-ups and as a good engineering practice to explicitly close resources and release them back to the system

socket.send( b"Server message #[_{0:_>10d}_] to client3".format( i ), zmq.NOBLOCK )

Last but not least :

Q : What is the correct way to connect a zmq PAIR between Ruby and Python?

as the API documentation explains:

ZMQ_PAIR sockets are designed for inter-thread communication across the zmq_inproc(7) transport and do not implement functionality such as auto-reconnection.

there is no best way to do this, as Python / Ruby are not a case of inter-thread communications. ZeroMQ has since v2.1+ explicitly warned, that the PAIR/PAIR archetype is an experimental and ought be used only with bearing that in mind.

One may always substitute each such use-case with a tandem of PUSH/PULL-simplex channels, providing the same comfort with a pair of a .send()-only + .recv()-only channels.

user3666197
  • 1
  • 6
  • 50
  • 92
  • I though that `PAIR` was the simplest way to start, I wanted a "Hello world" thing. I will try, `PUSH/PULL` then, thank you – Alejo Dev Jan 10 '20 at 21:45