一个Perl套接字在Linux下如何解析主机名? [英] How does a Perl socket resolve hostnames under Linux?
问题描述
$ 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屋!