为什么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(进程间通信)上工作吗?
2 个回答
197
正如 @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 传输,endpoint 应该被理解为一个 接口,后面跟着一个冒号和要使用的 TCP 端口号。
接口可以通过以下任一方式指定:
- 通配符 *,表示所有可用的接口。
- 分配给接口的主要 IPv4 地址,以数字形式表示。
- 操作系统定义的接口名称。
所以,如果你不使用通配符或接口名称,那么你必须使用数字形式的 IPv4 地址(而不是 DNS 名称)。
注意,这仅适用于使用 zmq_bind
!另一方面,使用 zmq_connect
时,使用 DNS 名称是完全可以的,文档中后面提到的 zmq_tcp 也说明了这一点:
当使用 zmq_connect() 将套接字连接到对等地址时,使用 tcp 传输,endpoint 应该被理解为一个对等地址,后面跟着一个冒号和要使用的 TCP 端口号。
对等地址可以通过以下任一方式指定:
- 对等方的 DNS 名称。
- 对等方的 IPv4 地址,以数字形式表示。
53
问题出在这一行:
subscriber.bind("tcp://localhost:5555")
试着改成:
subscriber.bind("tcp://127.0.0.1:5555")