Почему zeromq не работает на localhost? - PullRequest
62 голосов
/ 17 мая 2011

Этот код прекрасно работает:

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 использовать интерфейсы localhost?

Работает ли он только на IPC на той же машине?

Ответы [ 2 ]

153 голосов
/ 22 января 2012

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

Проблема в строке:

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

Попробуйте изменить на:

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

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

Документация для zmq_bind объясняет (выделение жирным шрифтом):

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

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

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

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

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

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

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

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

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

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

Проблема в строке:

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

Попробуйте изменить на:

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