【问题标题】:Why doesn't zeromq work on localhost?为什么 zeromq 在本地主机上不起作用?
【发布时间】:2011-08-26 19:27:03
【问题描述】:

这段代码效果很好:

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 上工作?

【问题讨论】:

    标签: python localhost zeromq


    【解决方案1】:

    正如@fdb 指出的那样:

    问题出在一行:

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

    尝试更改为:

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

    然而,这值得更多解释来理解原因。

    zmq_bind 的文档解释了(我的粗体强调):

    endpoint 参数是一个字符串,由以下两部分组成: transport://addresstransport 部分指定底层 要使用的传输协议。 地址部分含义具体 到所选的底层传输协议。

    由于您的示例使用 tcp 作为传输协议,我们查看 zmq_tcp 文档以发现(再次,粗体强调我的):

    当使用 zmq_bind() 将本地地址分配给套接字时 tcp 传输,endpoint 应被解释为 interface 后跟一个冒号和要使用的 TCP 端口号。

    接口可以通过以下任一方式指定:

    • 通配符 *,表示所有可用接口。
    • 分配给接口的主要 IPv4 地址,在其数字表示中
    • 操作系统定义的接口名称。

    因此,如果您不使用通配符或接口名称,则意味着您必须使用数字形式的 IPv4 地址(而不是 DNS 名称)。

    注意,这只适用于zmq_bind的使用!另一方面,将 DNS 名称与 zmq_connect 一起使用是完全可以的,稍后将在 zmq_tcp 的文档中进行讨论:

    当使用 zmq_connect() 将套接字连接到对等地址时 tcp 传输,端点应被解释为对等地址 后跟一个冒号和要使用的 TCP 端口号。

    可以通过以下任一方式指定对等地址:

    • 对等方的 DNS 名称。
    • 以数字表示的对等方的 IPv4 地址。

    【讨论】:

    • 这是一个奇怪的实现。
    • 啊一个非正交API
    • 这取决于底层套接字 API,它需要绑定到特定的 网络接口(或所有接口)并且主机名->接口不是一对一映射.相反,与具有多个地址的主机名建立连接是一个定义明确的操作。
    【解决方案2】:

    问题出在一行:

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

    尝试更改为:

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

    【讨论】:

    • 我喜欢使用更高的地址,例如 127.0.0.101,并根据应用程序改变它。比 IPC 插座更干净。
    • @fdb 是的,这解决了问题,但没有解释原因!它需要more explanation
    猜你喜欢
    • 1970-01-01
    • 2014-02-16
    • 2015-02-25
    • 2011-02-15
    • 2015-03-19
    • 2018-01-02
    • 2017-07-22
    • 2016-12-30
    • 1970-01-01
    相关资源
    最近更新 更多