如何检测系统是否支持 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文档中读到,如果表达式导致程序死亡,它会返回undef

我正在一台 Linux 机器上工作。

不要相信 Paranoid::Network::Socket 中的 has_ipv6() 函数。它返回误报,因为它只是检查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;
    }
}

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

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

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

最新更新