72

这段代码很好用:

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 吗?

4

2 回答 2

184

As @fdb points out:

The problem is at line:

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

try to change to:

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

However this deserves more explanation to understand why.

The documentation for zmq_bind explains (bold emphasis mine):

The endpoint argument is a string consisting of two parts as follows: transport://address. The transport part specifies the underlying transport protocol to use. The meaning of the address part is specific to the underlying transport protocol selected.

Since your example uses tcp as the transport protocol we look in the zmq_tcp documentation to discover (again, bold emphasis mine):

When assigning a local address to a socket using zmq_bind() with the tcp transport, the endpoint shall be interpreted as an interface followed by a colon and the TCP port number to use.

An interface may be specified by either of the following:

  • The wild-card *, meaning all available interfaces.
  • The primary IPv4 address assigned to the interface, in its numeric representation.
  • The interface name as defined by the operating system.

So, if you're not using wild-card or the interface name, then it means you must use an IPv4 address in numeric form (not a DNS name).

Note, this only applies to the use of zmq_bind! On the other hand it is perfectly fine to use a DNS name with zmq_connect as discussed later in the docs for zmq_tcp:

When connecting a socket to a peer address using zmq_connect() with the tcp transport, the endpoint shall be interpreted as a peer address followed by a colon and the TCP port number to use.

A peer address may be specified by either of the following:

  • The DNS name of the peer.
  • The IPv4 address of the peer, in its numeric representation.
于 2012-01-22T02:11:56.413 回答
53

问题在于:

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

尝试更改为:

subscriber.bind("tcp://127.0.0.1:5555")
于 2011-05-16T22:10:31.157 回答