2012-09-14 71 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()的操作。爲此,你仍然想以某種方式錯誤檢測實際的對象構造函數。