LinuxでPerlソケットはどのようにホスト名を解決しますか?
質問
すべてのツール(nslookup、curl、wget、firefoxなど)がアドレスを解決できる完全に機能するLinuxセットアップ(Ubuntu 8.04)があります(わかります)。それでも、次のコードは失敗します。
$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で検証済み
解決
クイックルックから、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」を追加して、正常に動作します。
マルチホームオプションは不必要なハッキングであり、他の問題が問題の根本原因であると思われます。
ステートメントがあることを確認してください
use IO::Socket::INET;
ソースコードの先頭。これを省略すると、おそらくエラーメッセージが表示されます。
オブジェクトメソッドが見つかりません" new&quot ;;経由で パッケージ" 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');