【问题标题】:zmq.error.ZMQError: Cannot assign requested addresszmq.error.ZMQError:无法分配请求的地址
【发布时间】:2026-01-07 23:30:01
【问题描述】:

我在 Amazon EC2 机器上有以下拉 - 发布者 ZMQ 架构:

我正在使用我的 EC2 Amazon 机器的公共 IP 地址。

我正在尝试通过 ZMQ PUSH 套接字从客户端发送数据到 ZMQ PULL 套接字服务器端,即:

import zmq
from zmq.log.handlers import PUBHandler
import logging
# from zmq.asyncio import Context

def main():
    ctx = zmq.Context()
    publisher = ctx.socket(zmq.PUB)
    # publisher.bind("tcp://*:5557")
    publisher.bind("tcp://54.89.25.43:5557")

    handler = PUBHandler(publisher)
    logger = logging.getLogger()
    logger.addHandler(handler)

    print("Network Manager CNVSS Broker listening")

    collector = ctx.socket(zmq.PULL)
    # collector.bind("tcp://*:5558")
    collector.bind("tcp://54.89.25.43:5558")

    while True:
        message = collector.recv()
        print("Publishing update %s" % message)
        publisher.send(message)

if __name__ == '__main__':
    main()

但是当我执行这个脚本时,我得到了这个错误:

(cnvss_nm) ubuntu@ip-172-31-55-72:~/cnvss_nm$ python pull_pub-nm.py 
Traceback (most recent call last):
  File "pull_pub-nm.py", line 28, in <module>
    main()
  File "pull_pub-nm.py", line 10, in main
    publisher.bind("tcp://54.89.25.43:5557")
  File "zmq/backend/cython/socket.pyx", line 547, in zmq.backend.cython.socket.Socket.bind
  File "zmq/backend/cython/checkrc.pxd", line 25, in zmq.backend.cython.checkrc._check_rc
zmq.error.ZMQError: Cannot assign requested address
(cnvss_nm) ubuntu@ip-172-31-55-72:~/cnvss_nm$ 

我已在服务器端将我的 IP 地址更改为 publisher.bind("tcp://*:5557")collector.bind("tcp://*:5558"),并且我的脚本正在运行:

(cnvss_nm) ubuntu@ip-x-x-x-x:~/cnvss_nm$ python pull_pub-nm.py 
Network Manager CNVSS Broker listening

但是从我的client-side code (added recently) 发送任何数据。

#include <zmq.hpp>
#include <zmq.h>
#include <iostream>
#include "zhelpers.hpp"

using namespace std;

int main(int argc, char *argv[])
{
    zmq::context_t context(1);
    /*
    std::cout << "Sending message to NM Server…\n" << std::endl; */

    zmq::socket_t subscriber(context, ZMQ_SUB);
    subscriber.connect("tcp://localhost:5557");
    subscriber.setsockopt(ZMQ_SUBSCRIBE, "", 0);

    zmq::socket_t sender(context, ZMQ_PUSH);
    sender.connect("tcp://localhost:5558");

    string firstMessage = "Hola, soy el cliente 1";

    while (1)
    {
        //  Wait for next request from client
        std::string string = s_recv(subscriber);

        std::cout << "Received request: " << string << std::endl;

        // Do some 'work'
        // sleep(1);

        //  Send reply back to client
        // zmq::message_t message(firstMessage.size() + 1);

        // Cualquiera de los dos se puede
        // memcpy(message.data(), firstMessage.c_str(), firstMessage.size() + 1);
        // s_send(sender, "Hola soy un responder 1");

        // sender.send(message);
    }
}

我认为我的不便在于我的EC2机器网络配置或设置服务器IP地址的方式。

当我在本地测试客户端和服务器时,一切正常。

是否有可能在我的 EC2 机器上执行一些转发或 NAT 操作?

我的客户没有到达服务器。

我有安全组规则上述端口 5557 和 5558。

如何解决这个不便?

【问题讨论】:

    标签: amazon-ec2 zeromq pyzmq


    【解决方案1】:

    我遇到过类似的情况,我在 EC2 上使用 ZMQ 并收到“无法分配请求的地址”。我也按照答案中的建议使用弹性 IP,但它对我不起作用。原来在EC2上,发送端(ZMQ.PUSH)需要绑定私网IP而不是公网IP,而接收端需要绑定公网IP,所以试图将服务器绑定到Elastic IP导致错误。在我将其更改为将服务器 ZMQ.PUSH 端绑定到私有 IP 并将客户端 ZMQ.PULL 绑定到弹性 IP(在同一端口上)之后,它就可以工作了。

    【讨论】:

      【解决方案2】:

      如何解决这种不便?

      1)
      如果对EC2地址有疑问,首先尝试测试逆向的.bind() / .connect(),这样EC2端的localhost地址分配就是退出游戏,您对已知 IP 地址的连接证明将不依赖于 EC2 端设置。

      2)
      接下来,鉴于没有关于 MCVE 客户端部分的详细信息,我可能对场景的想法有错误的理解,所以请耐心等待 - 只有这些兼容的 ZeroMQ Scalable Formal Communication Archetype sockets' 匹配从那时起一直可用,直到 2018/Q2 的 API v4.2.x:

      { PUB:  [  SUB,
                XSUB,
                None
                ],
        PULL: [ PUSH,
                None
                ],
        ...
        }
      

      3)
      有一个很好的工程实践是不要让未处理的异常发生,更何况,如果Context()-instance 可能仍然拥有 IP:PORT# (b)锁定资源(有时甚至超出 python 进程终止(我自己的天真和这种方式导致我过去黑暗历史中的实验陷入僵局:o))

      基础设施设置中的每个步骤都应该包含在错误处理语法子句中,最好包括一个finally: 部分,到目前为止,创建的资源偶尔会以优雅的方式被拆除,以防出现异常出去。这样,您的代码将防止永远挂起的孤儿,他们只能选择重新启动平台以摆脱这些人质,否则无法挽救人质。


      问题解决了,
      最后总结:

      如前所述,最初指出的问题(在.bind() / .connect() 阶段诊断)与 Amazon EC2 实例 IP 地址映射有关,作为任何传输类端点设置所需的术语,localhost:port#

      camdebu on Nov 1, 2012 5:07 PM 解释了所需的所有步骤:
      为您的 EC2 实例设置一个弹性 IP。然后,您将拥有一个静态 IP 地址。只要您将弹性 IP 指向 EC2 实例,它就不会产生任何费用。

      只要您的安全组设置正确,您就可以毫无问题地连接到您的新 IP 地址和端口。 -摄像头-

      • 检查您的安全组规则。确保您允许端口从实例外部进行通信。 (启用所有 TCP 并检查)。 [ 添加 Yesu Jeya Bensh.P ]

      最近发布的客户端代码,但显示了另一个问题,相互阻止,由不合作 zmq::socket_t sender( context, ZMQ_PUSH ),实际上从不发送一条消息。

      假设客户端进入上面发布的while(1)-loop,相关的对等点将无意中进入python制造的main()内的不可挽救的阻塞状态,因为:

      def main():
          ...
          collector = ctx.socket( zmq.PULL )
          #ollector.bind( "tcp://*:5558"           )
          collector.bind( "tcp://54.89.25.43:5558" )
      
          while True:
              message = collector.recv()           # THIS SLOC WILL BLOCK FOREVER HERE,
              ...                                  #      GIVEN <sender> NEVER SENDS...
      

      因此需要更加小心,以使事件流足够稳健,以免陷入这种或类似的无法挽救的相互阻塞。

      【讨论】:

      • 您好朋友感谢他们的建议。尊重他们:1. 颠倒 .bind() / .connect() 是什么意思。我在本地网络环境(两台机器连接在同一个交换机)中尝试我的代码,EC2 不在游戏中,并且进程消息传递它的工作原理。 2 从客户端,我有两个套接字:一个ZMQ_PUSH 套接字,它与服务器上的ZMQ_PULL 套接字连接。还有一个ZMQ_SUB 套接字,它与服务器上的ZMQ_PUB 套接字连接。这样,我的套接字定义根据我的架构或 ZMQ 模式,它们是兼容的。
      • 关于 第三个选项 - 3,我认为这是一个很好的选择,可以在我的 ZMQ 工作流程中管理与连接或连接相关的一些异常......但是,为什么我的架构的原因是在本地网络环境中工作,而不是在位于亚马逊 EC2 上的服务器上?以防万一...如果您需要了解客户端代码部分,我会放在这里...
      • reversed 表示,原本使用.bind() 的一方现在将尝试使用.connect(),反之亦然,这对ZeroMQ 基础架构的净影响为零设置,但可能会解决您的平台 IP 寻址不确定性。接下来,如果错误处理得当,代码将告知您失败的原因、位置和原因。 ,发布完整的 MCVE,包括重现问题的所有部分和数据,是 * 的一个已知质量标准
      • 你好,朋友。 One answer in this link给我解决不便的元素。在亚马逊 ec2 中,必须设置一个弹性 IP 地址并将其关联到我的 ec2 实例。有了这个,我解决了我的问题。 My code client side is here。关于处理错误。我可以在工作中思考try - exception - finally ... like this? 有什么建议吗?
      • 你好。你是对的,我发错了客户端代码,我很抱歉。碰巧我有以下方案:(i.stack.imgur.com/NDyPW.png“PUB/SUB+PUSH/PULL Messaging Broker”)My real client code sender is this。和上一个类似,但是这个客户端确实发送了消息。