一个Perl套接字在Linux下如何解析主机名? [英] How does a Perl socket resolve hostnames under Linux?

查看:136
本文介绍了一个Perl套接字在Linux下如何解析主机名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个(从我能说的)完美的Linux设置(Ubuntu 8.04),其中所有工具(nslookup,curl,wget,firefox等)都能够解析地址。然而,以下代码失败:

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

dieError:$!\\\
除非$ s;

我验证了以下内容:




  • Perl可以使用gethostbyname解析地址(即代码如下):



    my $ ret = gethostbyname('stackoverflow.com');
    打印inet_ntoa($ ret);


  • 原始源代码在Windows下工作


  • 这是它应该如何工作(即它应该解析主机名),因为LWP试图使用这个行为(实际上我试图调试为什么LWP不工作我)

  • 运行脚本不会发出DNS请求(因此甚至不会尝试解析名称)。验证与Wireshark


解决方案

从一个快速的看,下面的代码从IO :: Socket: :INET

  sub _get_addr {
my($ sock,$ addr_str,$ multi)= @_;
我的@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)使用inet_aton()从Socket.pm。这对Win32和Unix都有用,所以我猜这是破坏你的地方。



请参阅 Socket.xs

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

if(phe = gethostbyname(host)){
复制(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()为您。


I have a (from what I can tell) perfectly working Linux setup (Ubuntu 8.04) where all tools (nslookup, curl, wget, firefox, etc) are able to resolve addresses. Yet, the following code fails:

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

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

I verified the following things:

  • Perl is able to resolve addresses with gethostbyname (ie the code below works):

    my $ret = gethostbyname('stackoverflow.com'); print inet_ntoa($ret);

  • The original source code works under Windows

  • This is how it supposed to work (ie. it should resolve hostnames), since LWP tries to use this behavior (in fact I stumbled uppon the problem by trying to debug why LWP wasn't working for me)
  • Running the script doesn't emit DNS requests (so it doesn't even try to resolve the name). Verified with Wireshark

解决方案

From a quick look, the following code from 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;
}

suggests (if you look at the caller of this code) the work-around of adding MultiHomed => 1, to your code.

Without that work-around, the above code appears to try to call inet_aton("hostname.com") using the inet_aton() from Socket.pm. That works for me in both Win32 and Unix, so I guess that is where the breakage lies for you.

See Socket.xs for the source code of inet_aton:

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 );
        }
    }

It appears that the Perl gethostbyname() works better than the C gethostbyname() for you.

这篇关于一个Perl套接字在Linux下如何解析主机名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆