2010-02-09 2 views
1

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

In Perl, how can I check for the existence of Socket options without generating warnings?

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

#!/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 

Он выводит:

[email protected]$ ./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. 

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

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

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

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

+0

Почему кто-то отметил это? –

ответ

4

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

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'.

documentation for defined объясняет:

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

Например, с SO_BROADCAST

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

Выходной сигнал на моей машине

SO_BROADCAST = 6
+0

So Socket.pm определяет их как подпрограммы, которые возвращают правильное постоянное значение для перехода к таким функциям, как 'socket' и' getsockopt'? –

+0

@Robert Да, это общая идея. См. Http://perldoc.perl.org/perlsub.html # Constant-Functions –

+0

Я пробовал, и он не работает с IPV6_DONTFRAG. Я все еще получаю сообщение об ошибке «голый/строгий». –

0

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

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