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-доступ.