如何检测系统是否支持ipv6?

时间:2012-09-14 18:40:14

标签: perl ipv6

我终于设法修复了我的软件中的ipv6支持。不幸的是,现在它在每台ipv4机器上都崩溃了。这是错误的子程序:

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 doc中读到如果表达式导致程序死亡,它返回undef

我正在使用Linux机器。

2 个答案:

答案 0 :(得分:0)

您可以通过AF_INET6检测eval常数的存在:

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

但这还不够;仅仅因为OS支持该常量并不意味着这个特定的机器支持它。您必须测试整个socket()bind()操作是否也能正常运行。为此你仍然想以某种方式错误检测实际的对象构造函数。

答案 1 :(得分:0)

不要相信has_ipv6()中的Paranoid::Network::Socket功能。它返回false positive,因为它只是检查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 ($@) {
        return 0;
    }
    else {
        return 1;
    }
}
相关问题