zmq.error.ZMQError:无法分配请求的地址

问题描述 投票:1回答:2

我在Amazon EC2机器上有以下pull-publisher ZMQ架构:

我正在使用我的EC2亚马逊机器的公共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 codeadded 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
2个回答
1
投票

如何解决这个不便?

1) 如果怀疑EC2地址,首先尝试测试反向的.bind() / .connect(),以便EC2端本地主机地址分配在游戏中,并且您对已知IP地址的连接证明将不依赖于EC2端设置。

2) 接下来,鉴于没有关于MCVE的客户端部分的详细信息,我可能已经不情愿地得到了场景的想法,所以请耐心等待 - 从那时起只有这些兼容的ZeroMQ可扩展形式通信原型套接字匹配,直到2018 / Q2中的API v4.2.x:

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

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

基础设施设置中的每一步都应该包含在错误处理语法子句中,最好包括finally:部分,到目前为止,在异常出现的情况下,有时会以优雅的方式拆除所创建的资源。通过这种方式,您的代码将阻止永久挂起的孤儿,它只能重新启动平台,以便摆脱这些,否则无法挽救人质。


问题解决了, 最后的总结:

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

camdebu on Nov 1, 2012 5:07 PM解释了所需的所有步骤: 为您的EC2意图设置弹性IP。然后,您将拥有一个静态IP地址。只要您指向EC2实例,弹性IP就没有成本。

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

  • 检查您的安全组规则。确保允许端口从实例外部进行通信。 (启用所有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
投票

我有类似的情况,我在EC2上使用ZMQ并获得“无法分配请求的地址”。我也在答案中建议使用弹性IP,但它对我不起作用。事实证明,在EC2上,发送端(ZMQ.PUSH)需要绑定到私有IP而不是公共IP,而接收端需要绑定到公共IP,因此尝试将服务器绑定到弹性IP导致错误。在我将其更改为将服务器ZMQ.PUSH端绑定到专用IP并将客户端ZMQ.PULL绑定到弹性IP(在同一端口上)之后,它工作正常。

© www.soinside.com 2019 - 2024. All rights reserved.