我正在编写一个使用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 availablen";
程序如下:
调用netstat -aunt
解析结果
选择固定范围内的第一个端口,该端口没有出现在netstat列表中。
是否有更适合完成此任务的系统实用程序?
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)
首先,从您的代码中,看起来您正在尝试选择70000和79999之间的端口。你知道端口号最多只能达到65535,对吧?: -)
您当然可以这样做,尽管这种方法存在一些问题。第一个问题是netstat
输出在不同的操作系统之间是不同的,所以很难移植。第二个问题是,您仍然需要将代码包装在一个循环中,该循环在无法绑定到所选端口号的情况下再次尝试查找新端口号,因为在确定端口空闲和实际绑定端口之间存在竞争条件。
如果您正在使用的库允许您将端口号指定为0,并允许您在绑定套接字后调用getsockname()
,那么您应该这样做。使用0可以使系统选择任何空闲端口号,使用getsockname()
可以找出它选择的端口。
如果做不到这一点,实际上不调用netstat
可能会更有效,只是尝试在循环中找到不同的端口号。如果你成功了,就跳出这个循环。如果失败,将端口号增加1,返回,然后再试一次。