Perl: проверка на наличие опций сокетов - PullRequest
1 голос
/ 09 февраля 2010

Это продолжение моего предыдущего вопроса:

В Perl, как я могу проверить наличие опций Socket без генерации предупреждений?

Если я запускаю следующий код, я получаю ожидаемый результат:

#!/usr/bin/perl -w
use strict;
use diagnostics;
use Socket qw(:all);

my %opts;

if ( defined( eval { SO_REUSEPORT } ) ) {
    $opts{'SO_REUSEPORT'}
        =  {opt_level =>SOL_SOCKET,opt_name=>SO_REUSEPORT,opt_print=>\&sock_str_flag};
} else {
    print "SO_REUSEPORT undefined\n";
    $opts{'SO_REUSEPORT'}
        =  {opt_level =>0,opt_name=>0,opt_print=>undef};
}
=head
# IPV6 options
if ( defined( eval { IPV6_DONTFRAG } ) ) {
    $opts{'IPV6_DONTFRAG'}
        =  {opt_level =>IPPROTO_IPV6,opt_name=>IPV6_DONTFRAG,opt_print=>\&sock_str_flag};
} else {
    print "IPV6_DONTFRAG undefined\n";
    $opts{'IPV6_DONTFRAG'}
        =  {opt_level =>0,opt_name=>0,opt_print=>undef};
}
=cut

Это выводит:

anon@perl$ ./test.pl 
SO_REUSEPORT undefined

Но если я раскомментирую блок для IPV6_DONTFRAG, я получу:

Bareword "IPV6_DONTFRAG" not allowed while "strict subs" in use at ./test.pl line 17.
Bareword "IPV6_DONTFRAG" not allowed while "strict subs" in use at ./test.pl line 17.

Почему одно неопределенное голое слово приводит к тому, что оно срывается, а другое нет? И как может ошибка распространяться из блока eval { }?

Редактировать

Очевидно, SO_REUSEPORT экспортируется Socket.pm некоторым образом, так как он находится в массиве @EXPORT. Таким образом, очевидно, что он определен, но его использование выдает ошибку, которую перехватывает eval.

Это все еще не объясняет, что происходит с IPV6_DONTFRAG. Я полагаю, мне нужно определить его самому, а затем просто позвонить getsockopt, чтобы проверить, поддерживается ли он ...

Ответы [ 2 ]

4 голосов
/ 09 февраля 2010

Я рекомендую написать так:

if ( defined( &IPV6_DONTFRAG ) ) {
    $opts{'IPV6_DONTFRAG'}
        =  {opt_level =>IPPROTO_IPV6,opt_name=>&IPV6_DONTFRAG,opt_print=>\&sock_str_flag};
} else {
    print "IPV6_DONTFRAG undefined\n";
    $opts{'IPV6_DONTFRAG'}
        =  {opt_level =>0,opt_name=>0,opt_print=>undef};
}

Обратите внимание на добавленный амперсанд в значении для opt_name, что позволяет избежать ограничений из-за strict 'subs'.

Документация для defined объясняет:

Вы также можете использовать defined(&func), чтобы проверить, была ли когда-либо определена подпрограмма &func. На возвращаемое значение не влияют никакие предварительные декларации &func. Обратите внимание, что подпрограмма, которая не определена, все еще может вызываться: ее пакет может иметь метод AUTOLOAD, который заставляет его возникать при первом вызове - см. perlsub .

Например, с SO_BROADCAST

if (defined &SO_BROADCAST) {
  print "SO_BROADCAST = ", SO_BROADCAST, "\n";
}

на моей машине вывод

SO_BROADCAST = 6
0 голосов
/ 09 февраля 2010

Что касается проблемы голых слов IPV6_DONTFRAG, похоже, что Perl проверяет голые слова во время компиляции, а не во время выполнения, как описано здесь . Eval - это конструкция, которая поглощает ошибки времени выполнения, поэтому здесь она вам не поможет. Это все равно что пытаться обработать синтаксическую ошибку в C ++, вставив нарушающий код в блок try / catch.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...