如何选择端口号?

时间:2013-03-17 02:40:20

标签: network-programming zeromq

我正在编写一个程序,它使用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";

程序是:

  1. 调用netstat -aunt

  2. 解析结果

  3. 选择固定范围内第一个未出现在netstat列表中的端口。

  4. 是否有更适合实现此功能的系统实用程序?

2 个答案:

答案 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)