Perl套接字如何在Linux下解析主机名?

时间:2020-03-06 15:00:33  来源:igfitidea点击:

我有一个(据我所知)可以完美运行的Linux设置(Ubuntu 8.04),其中所有工具(nslookup,curl,wget,firefox等)都可以解析地址。但是,以下代码失败:

$s = new IO::Socket::INET(
    PeerAddr => 'stackoverflow.com',
    PeerPort => 80,
    Proto => 'tcp',
);

die "Error: $!\n" unless $s;

我验证了以下内容:

  • Perl能够使用gethostbyname解析地址(即下面的代码有效):my $ ret = gethostbyname('stackoverflow.com');打印inet_ntoa($ ret);
  • 原始源代码可在Windows下运行
  • 这是它应该如何工作的(即,它应该解析主机名),因为LWP尝试使用此行为(实际上,我通过尝试调试LWP不适用于我的原因偶然发现了该问题)
  • 运行脚本不会发出DNS请求(因此它甚至都不会尝试解析名称)。已通过Wireshark验证

解决方案

确保我们有对帐单

use IO::Socket::INET;

在源代码的开头。如果不进行此操作,则可能会收到错误消息:

Can't locate object method "new" via
  package "IO::Socket::INET"

除了可以使用Net :: DNS :: Resoler验证DNS是否正常工作之外,还可以在此处查看更多信息。

use Net::DNS;

my $res = Net::DNS::Resolver->new;

# Perform a lookup, using the searchlist if appropriate.
my $answer = $res->search('example.com');

快速浏览一下,IO :: Socket :: INET的以下代码

sub _get_addr {
    my($sock,$addr_str, $multi) = @_;
    my @addr;
    if ($multi && $addr_str !~ /^\d+(?:\.\d+){3}$/) {
        (undef, undef, undef, undef, @addr) = gethostbyname($addr_str);
    } else {
        my $h = inet_aton($addr_str);
        push(@addr, $h) if defined $h;
    }
    @addr;
}

建议(如果我们看一下此代码的调用者)建议在代码中添加MultiHomed => 1,的变通方法。

如果没有这种解决方法,上面的代码似乎试图使用Socket.pm中的inet_aton()来调用inet_aton(" hostname.com")`。这在Win32和Unix上都对我有效,所以我想这就是我们面临的问题。

有关inet_aton的源代码,请参见Socket.xs:

void
inet_aton(host)
    char *  host
    CODE:
    {
        struct in_addr ip_address;
        struct hostent * phe;

        if (phe = gethostbyname(host)) {
            Copy( phe->h_addr, &ip_address, phe->h_length, char );
        } else {
            ip_address.s_addr = inet_addr(host);
        }

        ST(0) = sv_newmortal();
        if(ip_address.s_addr != INADDR_NONE) {
            sv_setpvn( ST(0), (char *)&ip_address, sizeof ip_address );
        }
    }

对于我们来说,Perl gethostbyname()似乎比C gethostbyname()更好。

我们能否确切告诉我们代码如何失败?我们在那里有错误检查代码,但没有报告错误是什么!

我刚刚尝试了原始代码(在Mac OS X机器上添加了" use IO :: Socket :: INET",它可以正常工作。

我怀疑"多宿主"选项是不必要的破解,而其他一些问题是造成问题的根本原因。