Cómo configurar un PUB múltiple / SUB único Python ZMQ Ubuntu

Nov 19 2020

Tengo dos VM (VirtualBOx, Ubuntu 18.04 y python-zmq [16.0.2-2build2]) ejecutándose dentro de la misma máquina física (Win10). Ambas máquinas están configuradas como Bridge y pueden hacer ping correctamente a 192.168.1.66-192.168.1.55. He seguido este tutorialhttps://learning-0mq-with-pyzmq.readthedocs.io/en/latest/pyzmq/patterns/pubsub.html. Funciona si PUB (servidor) está configurado como

import zmq
import random
import sys
import time

port = "5557"
if len(sys.argv) > 1:
    port =  sys.argv[1]
    int(port)

context = zmq.Context()
socket = context.socket(zmq.PUB)
socket.bind("tcp://*:%s" % port)
while True:
    topic = random.randrange(9999,10005)
    messagedata = random.randrange(1,215) - 80
    print "%d %d" % (topic, messagedata)
    socket.send("%d %d" % (topic, messagedata))
    time.sleep(1)

Y el SUB (cliente) como

import sys
import zmq

port = "5557"
if len(sys.argv) > 1:
    port =  sys.argv[1]
    int(port)
    
if len(sys.argv) > 2:
    port1 =  sys.argv[2]
    int(port1)

# Socket to talk to server
context = zmq.Context()
socket = context.socket(zmq.SUB)

print "Collecting updates from weather server..."
socket.connect ("tcp://192.168.1.66:%s" % port)

if len(sys.argv) > 2:
    socket.connect ("tcp://localhost:%s" % port1)
# Subscribe to zipcode, default is NYC, 10001
topicfilter = "10001"
socket.setsockopt(zmq.SUBSCRIBE, topicfilter)

# Process 5 updates
total_value = 0
for update_nbr in range (5):
    string = socket.recv()
    topic, messagedata = string.split()
    total_value += int(messagedata)
    print topic, messagedata

print "Average messagedata value for topic '%s' was %dF" % (topicfilter, total_value / update_nbr)

Como quiero un solo cliente (SUB) con múltiples servidores (PUB) donde pueden ser cientos, incluso miles, es inviable configurar una única IP para cada PUB. ¿Hay alguna forma de suscribirse sin especificar la IP? O al menos uno de transmisión. Intenté configurar en el cliente en socket.connect ("tcp://IP:%s" % port):

"*"

Da el error:

Traceback (most recent call last):
  File "sub_client.py", line 18, in <module>
    socket.connect ("tcp://*:%s" % port)
  File "zmq/backend/cython/socket.pyx", line 528, in zmq.backend.cython.socket.Socket.connect (zmq/backend/cython/socket.c:5980)
  File "zmq/backend/cython/checkrc.pxd", line 25, in zmq.backend.cython.checkrc._check_rc (zmq/backend/cython/socket.c:8400)
zmq.error.ZMQError: Invalid argument

192.168.1.1 (GW), 192.168.1.255 (difusión), localhost / 127.0.0.1 y su IP (192.168.1.55) -> no recibe mensajes

192.168.1.66 (IP del servidor) -> Recibe mensajes pero no es práctico en un sistema a gran escala

¿Alguna forma de resolver esto?

Respuestas

user3666197 Nov 19 2020 at 22:21

P : ¿ Alguna forma de resolver esto?

Evite ir en contra de cualquier propiedad documentada por API. Mientras que un .bind()-method para la tcp://-transport-class puede intentar enlazarse a cualquier localhostdirección IP -side, el .connect()-method, por razones obvias, no puede.

Como se notificó en el ZMQError:

socket.connect ("tcp://*:%s" % port)
zmq.error.ZMQError: Argumento no válido

Corrija el destino de la dirección IP, donde el
.connect( "tcp://{0:}:{1:}".format( IP, PORT ) )método intentará "hacer sonar para obtener conexión".