zmq.error.ZMQError: Cannot assign requested address

zmq.error.ZMQError: Cannot assign requested address

我在 Amazon EC2 机器上有以下 pull - publisher ZMQ 模式:

我正在使用我的 EC2 Amazon 机器的 Public 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 ( ) 发送任何数据。

#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。

如何解决这个不便?

How to solve this inconvenience?

1 )
如果对 EC2 地址有疑问,首先尝试测试反向 .bind() / .connect(),这样 EC2 端的本地主机地址分配就不再适用,并且您对已知 IP 地址的连接证明将不依赖于 EC2 端的设置。

2 )
接下来,MCVE的client-side部分没有详细介绍,可能是我的场景思路有误,大家多多包涵和我一起——只有这些兼容的 ZeroMQ 可扩展正式通信原型 sockets' 匹配可用,直到 API v4.2.x 在 2018/Q2:

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

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

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


问题已解决,
最终总结:

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

camdebu on Nov 1, 2012 5:07 PM explained all the steps needed:
Setup an Elastic IP to your EC2 isntance. You will then have a static IP address. There's no cost for the Elastic IP as long as you have it pointed to an EC2 instance.

You should then have no problem connecting to your new IP Address and port as long as your security group is setup correctly. -Cam-

  • Check your Security Group Rule. Make sure you allow the port to communicate from outside the instance. (Enable All TCP and Check). [ added Yesu Jeya Bensh.P ]

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

如果客户端进入上面发布的 while(1)-loop,关联的对等方将无意中进入 python-made 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...

因此要更加小心,以使事件流足够稳健,永远不会陷入这种或类似的不可挽救的相互阻塞。

我遇到过类似的情况,我在 EC2 上使用 ZMQ 并获得 "Cannot assign requested address." 我也按照答案中的建议使用了 Elastic IP,但它对我不起作用。原来在EC2上,发送方(ZMQ.PUSH)需要绑定到私有IP而不是public,而接收方需要绑定到public IP,所以试图将服务器绑定到弹性 IP 导致了错误。在我将其更改为将服务器 ZMQ.PUSH 端绑定到私有 IP 并将客户端 ZMQ.PULL 绑定到弹性 IP(在同一端口上)之后,它起作用了。