IO::Socket::INET->new возвращает неопределенное значение при ошибке?

У меня есть следующий код (часть более крупного скрипта)

my $lsn = IO::Socket::INET->new(Listen => 1, LocalPort => 0); # just use any available port.
$port = $lsn->sockport();

Я получаю ошибку Can't call method "sockport" on an undefined value,

Документация для IO::Socket::INET не много говорит по этому вопросу: https://perldoc.perl.org/IO/Socket/INET.html (есть ли лучшее место для поиска? Не слишком знаком с этим модулем).

Странно то, что я недавно изменил это, прежде чем он передавал ненулевой, случайно сгенерированный номер порта, и он иногда ломался, когда порт использовался.

Я проверил прохождение 0 на моей локальной машине с Windows (опять же, в документации, похоже, не упоминается, как заставить его выбрать порт для привязки), и это, казалось, заставило его "выбрать любой доступный порт", что я и хотел, но, возможно, это ведет себя по-разному на Solaris (где возникла эта проблема)?

2 ответа

Решение

IO::Socket::INET->new работает как большинство Perl-конструкторов: он возвращает экземпляр класса в случае успеха, ложное значение при ошибке. Есть какой-то побочный канал, чтобы узнать причину ошибки. То, что это ложное значение намеренно не задокументировано, все, что имеет значение, это ложь.

Это приводит к общей схеме my $obj = Class->new or die $reason;, В случае IO::Socket вы получаете ошибку от $@ (что довольно грубо).

my $port = 999;
my $lsn = IO::Socket::INET->new(Listen => 1, LocalPort => $port)
    or die "Couldn't listen on port $port: $@";

# Couldnt listen on port 999: Permission denied at -e line 1.

Я протестировал передачу 0 на моей локальной машине с Windows (опять же, в документации, похоже, не упоминается, как заставить его выбрать порт для привязки), и это, похоже, заставило его "выбрать любой доступный порт", что я и сделал. хотел, но, возможно, он ведет себя по-разному в Solaris (где эта проблема возникла)?

Да, это зависит от реализации. IO::Socket::INET - это просто тонкий слой вокруг библиотеки Socket, который использует bind, Если вы пройдете bind порт 0 он найдет порт для вас. Это в целом верно для всех современных реализаций.

Windowsbind...

Для TCP/IP, если порт указан как ноль, поставщик услуг назначает приложению уникальный порт из диапазона портов динамического клиента. В Windows Vista и более поздних версиях диапазон динамических клиентских портов составляет от 49152 до 65535. Это изменение по сравнению с Windows Server 2003 и более ранними версиями, где диапазон динамических клиентских портов составлял от 1025 до 5000.

Он пытается подключиться к привилегированному порту (на Solaris менее 1024)? Если это так, это может быть проблема с разрешениями, и для привязки потребуется root-доступ.

Другие вопросы по тегам