Подтвердить что ты не робот

Почему zeromq не работает на localhost?

Этот код отлично работает:

import zmq, json, time

def main():
    context = zmq.Context()
    subscriber = context.socket(zmq.SUB)
    subscriber.bind("ipc://test")
    subscriber.setsockopt(zmq.SUBSCRIBE, '')
    while True:
        print subscriber.recv()

def main():
    context = zmq.Context()
    publisher = context.socket(zmq.PUB)
    publisher.connect("ipc://test")
    while True:
        publisher.send( "hello world" )
        time.sleep( 1 )

Но этот код не работает:

import zmq, json, time

def recv():
    context = zmq.Context()
    subscriber = context.socket(zmq.SUB)
    subscriber.bind("tcp://localhost:5555")
    subscriber.setsockopt(zmq.SUBSCRIBE, '')
    while True:
        print subscriber.recv()

def send():
    context = zmq.Context()
    publisher = context.socket(zmq.PUB)
    publisher.connect("tcp://localhost:5555")
    while True:
        publisher.send( "hello world" )
        time.sleep( 1 )

Возникает эта ошибка:

ZMQError: Нет такого устройства

Почему zeromq не может использовать локальные интерфейсы?

Работает ли он только на IPC на одном компьютере?

4b9b3361

Ответ 1

Проблема находится в строке:

subscriber.bind("tcp://localhost:5555")

попытайтесь изменить на:

subscriber.bind("tcp://127.0.0.1:5555")

Ответ 2

Как указывает @fdb:

Проблема находится в строке:

subscriber.bind("tcp://localhost:5555")

попытайтесь изменить на:

subscriber.bind("tcp://127.0.0.1:5555")

Однако это заслуживает большего объяснения, чтобы понять, почему.

Документация для zmq_bind объясняет (смелый акцент мой):

Аргумент конечной точки - это строка, состоящая из двух частей: transport://address. Транспортная часть указывает основные транспортный протокол для использования. Значение адресной части является специфическим к выбранному транспортному протоколу.

Поскольку ваш пример использует tcp в качестве транспортного протокола, мы смотрим в документации zmq_tcp, чтобы обнаружить (опять же, смелый акцент мой):

При назначении локального адреса сокету с помощью zmq_bind() с tcp, конечная точка должна интерпретироваться как интерфейс за которым следует двоеточие и номер порта TCP.

Интерфейс может быть указан одним из следующих:

  • Дикая карта *, означающая все доступные интерфейсы.
  • Основной IPv4-адрес, назначенный интерфейсу, в его числовом представлении.
  • Имя интерфейса, определяемое операционной системой.

Итак, если вы не используете wild-card или имя интерфейса, значит, вы должны использовать IPv4-адрес в числовой форме (не DNS-имя).

Обратите внимание, что это относится только к использованию zmq_bind! С другой стороны, отлично использовать DNS-имя с zmq_connect, как описано ниже в документах для zmq_tcp:

При подключении сокета к одноранговому адресу с помощью zmq_connect() с tcp-транспорт, конечная точка должна интерпретироваться как адрес однорангового узла за которым следует двоеточие и номер порта TCP.

Одноранговый адрес может быть указан одним из следующих способов:

  • DNS-имя однорангового узла.
  • Адрес IPv4 однорангового узла в его числовом представлении.