为啥 zeromq 在本地主机上不起作用?

Posted

技术标签:

【中文标题】为啥 zeromq 在本地主机上不起作用?【英文标题】: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 上工作?

【问题讨论】:

【参考方案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。

以上是关于为啥 zeromq 在本地主机上不起作用?的主要内容,如果未能解决你的问题,请参考以下文章

Facebook登录按钮在本地主机上不起作用

自定义重定向在本地主机上不起作用

ReCAPTCHA 在本地主机上不起作用

本地 JQuery 和 JQuery 移动文件在本地主机上不起作用

htaccess 规则在本地主机上不起作用

在本地主机上运行 docker 容器不起作用