我正在编写一个程序,它使用ZeroMQ与同一台机器上的其他正在运行的程序进行通信。我想在运行时选择端口号以避免发生冲突。以下是我为实现此目的而编写的一段代码示例。
#!/usr/bin/perl -Tw
use strict;
use warnings;
my %in_use;
{
local $ENV{PATH} = '/bin:/usr/bin';
%in_use = map { $_ => 1 } split /\n/, qx(
netstat -aunt |\
awk '{print \$4}' |\
grep : |\
awk -F: '{print \$NF}'
);
}
my ($port) = grep { not $in_use{$_} } 50_000 .. 59_999;
print "$port is available\n";
程序是:
调用netstat -aunt
解析结果
选择固定范围内第一个未出现在netstat列表中的端口。
是否有更适合实现此功能的系统实用程序?
答案 0 :(得分:2)
首先,从您的代码看起来您似乎正在尝试选择70000和79999之间的端口。您确实知道端口号最多只能达到65535,对吧? : - )
你当然可以这样做,即使这种方法存在一些问题。第一个问题是netstat
输出在不同的操作系统之间有所不同,因此很难移植它。第二个问题是你仍然需要将代码包装在一个循环中,该循环再次尝试找到一个新的端口号,以防它无法绑定到所选的端口号,因为在确定端口是免费的之间存在竞争条件并实际上绑定它。
如果您使用的库允许您将端口号指定为0并允许您在绑定后在套接字上调用getsockname()
,那么您应该这样做。使用0会使系统选择任意空闲端口号,使用getsockname()
可以找出它选择的端口。
如果不这样做,实际上可能更有效的是不打扰调用netstat
并尝试在循环中找到不同的端口号。如果成功,请从循环中断开。如果失败,请将端口号递增1,然后返回,然后重试。
答案 1 :(得分:1)
context = zmq.Context()
socket = context.socket(zmq.ROUTER)
port_selected = socket.bind_to_random_port('tcp://*', min_port=6001, max_port=6004, max_tries=100)