是否有干净且与操作系统无关的方法来从Perl中确定本地机器的IP地址?
到目前为止,我找到了以下解决方案:
解析 ifconfig 和 ipconfig 的输出结果(很麻烦,不同版本的Windows具有不同的ipconfig输出结果)
连接到已知的IP地址并检查套接字的本地IP地址(如果无法建立连接,则无法使用此方法,并且只能确定一个IP地址)
有更好的建议吗?
是否有干净且与操作系统无关的方法来从Perl中确定本地机器的IP地址?
到目前为止,我找到了以下解决方案:
解析 ifconfig 和 ipconfig 的输出结果(很麻烦,不同版本的Windows具有不同的ipconfig输出结果)
连接到已知的IP地址并检查套接字的本地IP地址(如果无法建立连接,则无法使用此方法,并且只能确定一个IP地址)
有更好的建议吗?
您还有一些其他选项,包括您提出的“建立与已知IP的网络连接并检查套接字的本地IP地址”解决方案。
然而,在这种情况下(建立网络连接),该文章指出:
不存在主机IP地址的概念。
网络接口具有IP地址,而不是主机,单个网络接口可以有许多(虚拟)IP地址。操作系统路由子系统决定使用哪个网络接口和IP地址连接到远程计算机。如果您的计算机只有一个外部网络接口,并且此接口只有一个IP地址,则通常称此IP地址为计算机地址,但这是不准确的。
例如,如果计算机通过虚拟接口连接到VPN,则会使用此界面的IP地址连接到VPN上的另一台计算机,而不是外部IP地址。
在其他解决方案中:Sys::Hostname
- 如果它能够生成可解析的主机名,则有效。
use Sys::Hostname;
use Socket;
my $addr = inet_ntoa((gethostbyname(hostname))[4]);
print "$addr\n";
Net::Address::IP::Local 看起来很有前途。
use Net::Address::IP::Local;
# Get the local system's IP address that is "en route" to "the internet":
my $address = Net::Address::IP::Local->public;
在我的情况下,我需要一个没有任何非核心依赖的解决方案。在研究Net::Address::IP::Local中的代码后,我得出了这个结论:
#!/usr/bin/env perl
use strict;
use warnings;
use IO::Socket::INET;
my $local_ip_address = get_local_ip_address();
print "$local_ip_address\n";
# This idea was stolen from Net::Address::IP::Local::connected_to()
sub get_local_ip_address {
my $socket = IO::Socket::INET->new(
Proto => 'udp',
PeerAddr => '198.41.0.4', # a.root-servers.net
PeerPort => '53', # DNS
);
# A side-effect of making a socket connection is that our IP address
# is available from the 'sockhost' method
my $local_ip_address = $socket->sockhost;
return $local_ip_address;
}
get_local_ip_address()
应该返回与Net::Address::IP::Local->public_ipv4
相同的字符串。
如果需要,您可以将IO::Socket::INET构造函数中的PeerAddr
属性更改为本地DNS服务器。
要获取所有接口的IP地址,请使用IO::Interface::Simple:
perl -MIO::Interface::Simple '-Esay $_->address for grep { $_->is_running && defined $_->address } IO::Interface::Simple->interfaces'
如果您不关注127.0.0.1(回环),则可以通过$_->is_loopback
进行过滤。
我在Linux和Solaris上使用IO::Interface非常成功,我认为它甚至可以在AIX上工作,但我不能确定。在search.cpan.org、rt.cpan.org和ActiveState的各个网站上搜索,看起来IO::Interface可能在Windows上遇到了构建问题。我想唯一知道它是否可用的方法是在PPM中搜索io-interface。
使用WMI?
提取IP地址示例(使用Powershell,但很清楚正在发生什么)
从Perl访问WMI的示例(不是相同的WMI函数,但是过程再次相当清晰)
编辑:在Google codesearch上搜索Networkadapterconfiguration和语言“perl”后:
编辑2:实际上,OCS代码似乎包含了大多数平台执行此操作的代码,因此虽然可能没有一组代码可以执行此操作,但您可以重用它们的想法。然而,它是GPL许可的。
例如,这里是Solaris代码。其他部分覆盖了BSD、Linux、MacOS等。
在Windows上我使用
foreach (split(/\r?\n/,`netstat -r`))
{
next unless /^\s+0.0.0.0/;
@S = split(/\s+/);
# $S[3] = Default Gateway
# $S[4] = Main IP
}
以0.0.0.0开头的第一行是默认网关。可能会有多个网关。 以255.255.255.255开头的行也很有用。netstat -r和route print是相同的。
可以适用于OSX,但对Linux不太有帮助。
Net::Address::IP::Local 可以正常工作,但由于原帖作者要求获取所有本地地址,我认为这个更好:
http://www.perlmonks.org/?node_id=166951
我使用适用于Windows XP的ActivePerl,它对我很有效。