【问题标题】:Connect to first free port with TCP using 0MQ使用 0MQ 通过 TCP 连接到第一个空闲端口
【发布时间】:2013-05-17 23:37:27
【问题描述】:

我正在编写一个分布式搜索算法,其中代理需要在 TCP 套接字上侦听传入连接。在某些时候,代理应该绑定一个空闲的 TCP 端口。端口号并不重要,但代理应该将他/她的侦听端口号发送给其他代理。

我想这是正确的做法:

socket.bind("tcp://*:0");

Socket 绑定成功,但是如何获取 socket 绑定的端口号?我在zmq_getsockopt 手册页中看不到返回端口号的任何选项代码。

【问题讨论】:

标签: c++ sockets zeromq


【解决方案1】:

使用 Zeromq,您可以使用字符串来绑定或连接。它以 protecol 开头,在您的情况下为tcp://,这没关系。然后你有一个'*',它代表所有可用的设备。然后在您的情况下以端口号 :0 结束。

socket.bind("tcp://*:2424)

会尝试绑定端口 2424。如果你运行 man zmq_tcp 他们建议端口号高于 1024。基本上你应该提前知道你的端口号,而不是在绑定之后。在较新的版本 3.2 中,还可以指定端口 :0 或 :* 然后操作系统将决定端口的位置。这可以通过 socket.getsockopt() 检索,如下例所示:

zmq::context_t context(1);
zmq::socket_t sock(context, ZMQ_REP);
char port[1024]; //make this sufficiently large. 
                 //otherwise an error will be thrown because of invalid argument. 
size_t size = sizeof(port);
try{
    sock.bind("tcp://*:*");
}
catch (zmq::error_t&e ){
    cerr << "couldn't bind to socket: " << e.what();
    return e.num();
}
sock.getsockopt( ZMQ_LAST_ENDPOINT, &port, &size );
cout << "socket is bound at port " << port << endl;

这将给出例如以下输出:

socket is bound at port tcp://0.0.0:53269

所以你仍然需要从字符串 "tcp://0.0.0.0:53269" 中解析 53269 希望这会有所帮助

【讨论】:

  • @sorush 您的上一条评论中有一个奇怪的错字。我想你打算写“端口号”。我不知道是否可以让操作系统决定,但我看看。
  • 糟糕!对此感到抱歉;)它不再可编辑(有人杀了我)所以我删除了。它很安静,并且已经是 zmq 中的一个可用功能。 This discussion on github 描述了如何正确地做到这一点。但它不适用于 C++。我认为这是 ZMQ 的 C++ 端口的错误。我还没有用 C 测试过...
  • @soroush 您使用的是 3.2 版吗?我经常使用 2.x 版,但根据 C -api(3.2 版),你应该使用 ZMQ_LAST_ENDPOINT,如果你将它传递给 socket.get_sockopt(),它可能会起作用,因为 C++ api 包含 C api。那么字符串应该是 tcp://*:*
  • @soroush 我已经更新了我的答案以更好地满足您的标准。
  • 我不同意您关于应该提前知道端口号的说法。即使您在绑定到某个端口之前检查它是否可用,该端口仍然可能在您的检查和绑定尝试之间变得不可用。所以我更喜欢你使用getsockopt的例子。
猜你喜欢
  • 2011-03-17
  • 1970-01-01
  • 2016-04-10
  • 2019-06-25
  • 2011-12-10
  • 2014-05-02
  • 2011-04-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多