2013-03-17 5 views
0

Я пишу программу, которая использует 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. Invoke NetStat -aunt

  2. разбора результата

  3. выбрать первый порт на фиксированном диапазоне, который не появляется в списке нетстата.

Есть ли системная утилита, которая лучше подходит для этого?

ответ

0
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) 
+2

Сладкий! Однако, похоже, что метод bind_to_random_port (...) существует только для драйвера Python. Если посмотреть на это, я обнаружил, что ZMQ v3 поддерживает номер подстановочного порта, который вы можете отслеживать с помощью getsockopt (ZMQ_LAST_ENDPOINT). – ddoxey

2

Прежде всего, из вашего кода, похоже, вы пытаетесь выбрать порт между 70000 и 79999. Вы знаете, что номера портов только доходят до 65535, верно? :-)

Вы можете, конечно, сделать это таким образом, хотя есть пара проблем с подходом. Первая проблема заключается в том, что вывод netstat отличается от разных операционных систем, поэтому трудно сделать это переносимо. Вторая проблема заключается в том, что вам все равно нужно обернуть код в цикле, который снова пытается найти новый номер порта, если не удалось привязать к выбранному номеру порта, потому что есть условие гонки между констатацией того, что порт свободен и фактически привязаны к нему.

Если библиотека, которую вы используете, позволяет указать номер порта как 0 и позволяет вам позвонить getsockname() в сокет после его привязки, тогда вы должны просто сделать это. Используя 0, система выбирает номер свободного порта, а с getsockname() вы можете узнать, какой порт он выбрал.

В противном случае, вероятно, было бы более эффективным не беспокоиться о вызове netstat и просто попытаться найти разные номера портов в цикле. Если вам это удастся, выйдите из цикла. Если вы терпите неудачу, увеличьте номер порта на 1, вернитесь назад и повторите попытку.

+0

О, это немного глупое - исправлен неверный диапазон портов. Нет, ZMQ не принимает номер порта, равный нулю. Да, это расовое состояние, из-за которого я колеблюсь. – ddoxey

Смежные вопросы