3

我有一个(据我所知)完美运行的 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'); print inet_ntoa($ret);

  • 原始源代码在Windows下工作

  • 这就是它应该如何工作(即它应该解析主机名),因为 LWP 试图使用这种行为(事实上,我通过尝试调试为什么 LWP 不为我工作而偶然发现了这个问题)
  • 运行脚本不会发出 DNS 请求(因此它甚至不会尝试解析名称)。通过 Wireshark 验证
4

3 回答 3

7

快速浏览一下,来自 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,到您的代码的解决方法。

如果没有这种解决方法,上面的代码似乎会尝试inet_aton("hostname.com")使用来自 Socket.pm 的 inet_aton() 进行调用。这在 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() 更适合您。

于 2008-10-02T05:11:35.577 回答
0

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

我刚刚尝试了原始代码(在我的 Mac OS X 机器上添加了“使用 IO::Socket::INET”,它工作正常。

我怀疑 Multihomed 选项是不必要的黑客攻击,而其他一些问题是您问题的根本原因。

于 2008-10-06T16:36:59.297 回答
-1

确保你有声明

use IO::Socket::INET;

在源代码的开头。如果您忽略它,您可能会收到错误消息:

无法通过包“IO::Socket::INET”定位对象方法“new”

除此之外,您还可以使用 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');
于 2008-10-02T04:44:17.530 回答