Como configurar um múltiplo PUB / único SUB python ZMQ Ubuntu

Nov 19 2020

Tenho duas VMs (VirtualBOx, Ubuntu 18.04 e python-zmq [16.0.2-2build2]) em execução na mesma máquina física (Win10). Ambas as máquinas são configuradas como Bridge e podem executar ping com êxito em 192.168.1.66-192.168.1.55. Eu segui este tutorialhttps://learning-0mq-with-pyzmq.readthedocs.io/en/latest/pyzmq/patterns/pubsub.html. Funciona se PUB (servidor) estiver 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)

E o 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 eu quero um único cliente (SUB) com vários servidores (PUB) onde eles podem ser centenas ou milhares, é inviável configurar um único IP para cada PUB. Existe uma maneira de assinar sem especificar o IP? Ou pelo menos uma transmissão. Tentei configurar no cliente em socket.connect ("tcp://IP:%s" % port):

"*"

Dá o erro:

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 (transmissão), localhost / 127.0.0.1 e seu IP (192.168.1.55) -> não recebe mensagens

192.168.1.66 (IP do servidor) -> Recebe mensagens, mas não é prático em um sistema de grande escala

Alguma maneira de resolver isso?

Respostas

user3666197 Nov 19 2020 at 22:21

P : alguma maneira de resolver isso?

Evite ir contra qualquer propriedade documentada pela API. Enquanto um .bind()-método pode para a tcp://-transport-class tentar de fato ligar-se a qualquer localhostendereço IP, o .connect()-método, por razões óbvias, não pode.

Conforme notificado em ZMQError:

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

Corrija o destino do endereço IP, onde o
.connect( "tcp://{0:}:{1:}".format( IP, PORT ) )-método tentará "ligar para obter a conexão".