2012-09-14 72 views
2

我终于设法在我的软件中修复ipv6支持。不幸的是,现在它在每台仅有ipv4的机器上崩溃。下面是错误的子程序:如何检测系统是否支持ipv6?

sub init 
{ 
    my ($self, %opts) = @_; 

    # server options defaults 
    my %defaults = (StartBackground => 0, ServerPort => 3000); 

    # set options or use defaults 
    map { $self->{$_} = (exists $opts{$_} ? $opts{$_} : $defaults{$_}) } 
     keys %defaults; 

    $self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'}, Socket::AF_INET6); 

    return $self; 
} 

这里的问题是在倒数第二行:

$self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'}, Socket::AF_INET6); 

由于在IPv4上只有它死在抱怨一个不支持的地址族(机,这是第二个参数传递给new函数)。

基本上,我需要做的是:

if (it_supports_ipv6()) { 
    $self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'}, Socket::AF_INET6); 
} 
else { 
    $self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'}); 
} 

但如何实现像it_supports_ipv6()的功能?

我试着用eval使用下面的语法,但它不工作:

my $ipv6_success = eval { $self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'}, Socket::AF_INET6); }; 
if (!defined($ipv6_success)) { 
    $self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'}); 
} 

的逻辑是,我在eval文档,它返回undef读过如果表达式导致程序死。

我正在使用Linux机器。

+1

它会死机还是死?如果它只是在死亡,你可以在['eval'](http://search.cpan.org/perldoc?perlfunc#eval)调用中用'Socket :: AF_INET6'引用包装行。 – mob

+4

'Paraniod :: Network :: Socket'是Socket的包装器,提供BOOL'has_ipv6()' – charlesbridge

+0

@mob,是的,你说得对,它死了!我会检查评估。 – Zagorax

回答

0

不要相信函数Paranoid::Network::Socket。它返回误报,因为它只是检查Perl是否支持它,但是这还不够(系统,例如,系统可能没有加载ipv6内核模块)。

我结束了以下功能,它似乎工作正常。

use IO::Socket::IP; 

sub supports_ipv6 { 
    my $has_ipv6; 

    eval { 
     $has_ipv6 = IO::Socket::IP->new (
      Domain => PF_INET6, 
      LocalHost => '::1', 
      Listen => 1) or die; 
    }; 

    if ([email protected]) { 
     return 0; 
    } 
    else { 
     return 1; 
    } 
} 
0

您可以通过eval检测AF_INET6不变的存在:

use constant HAS_AF_INET6 => defined eval { Socket::AF_INET6() }; 

但是,这是不是真的足够了;仅仅因为操作系统支持这个常量并不意味着这个特定的机器支持它。您必须测试整个socket()bind()的操作。为此,你仍然想以某种方式错误检测实际的对象构造函数。