2010-02-09 11 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. 

为什么一个未定义的裸字使其BARF和其他不?那么错误如何传播出eval { }块?

编辑

显然,SO_REUSEPORTSocket.pm以某种方式,因为它是@EXPORT阵列中导出。所以显然它已被定义,但使用它会引发eval捕获的错误。

这仍然不能解释IPV6_DONTFRAG是怎么回事。我想我需要定义它自己,然后就打电话getsockopt,以检查它是否支持...

+0

为什么有人标记这个? – 2010-02-13 22:04:28

回答

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

因此,Socket.pm将这些定义为子例程,它们将正确的常量值传递给像'socket'和'getsockopt'这样的函数? – 2010-02-09 18:18:33

+0

@Robert是的,这是一般的想法。请参阅http://perldoc.perl.org/perlsub。html#Constant-Functions – 2010-02-09 18:49:43

+0

我试过了,它不适用于IPV6_DONTFRAG。我仍然得到了裸词/严格的潜在错误。 – 2010-02-10 16:24:55

0

至于到IPV6_DONTFRAG裸字的问题,它看起来像Perl的检查在编译时裸字,没有运行时间,如记录here。 Eval是一个吞噬运行时错误的结构,所以它不会帮助你。这就像试图通过在try/catch块中粘贴有问题的代码来处理C++中的语法错误。