Как я могу определить IP-адреса локальной машины из Perl? - PullRequest
8 голосов
/ 01 декабря 2008

Существует ли чистый и независимый от ОС способ определения IP-адресов локальной машины из Perl?

Пока я нашел следующие решения:

  • анализ выходных данных ifconfig и ipconfig (жесткие, разные версии Windows имеют разные выходные данные ipconfig)

  • установить сетевое соединение с известным IP-адресом и проверить локальный IP-адрес сокета (не будет работать, если я не могу установить соединение и определю только один IP-адрес)

Есть лучшее предложение?

Ответы [ 11 ]

15 голосов
/ 14 августа 2012

В моем случае мне нужно решение без каких-либо неосновных зависимостей. Я придумал это после изучения кода в 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.

При желании вы можете изменить атрибут PeerAddr (в аргументах конструктора для IO :: Socket :: INET) на локальный DNS-сервер.

15 голосов
/ 01 декабря 2008

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;
15 голосов
/ 01 декабря 2008

У вас также есть несколько других опций , включая ваше решение «установить сетевое соединение с известным IP-адресом и проверить локальный IP-адрес сокета».

В этом случае (установление сетевого подключения), однако, эта статья указывает, что:

IP-адрес хоста не существует.
Сетевые интерфейсы имеют IP-адреса, а не хосты, и один сетевой интерфейс может иметь много (виртуальных) IP-адресов. Подсистема маршрутизации операционной системы решает, какой сетевой интерфейс и IP-адрес использовать для подключения к удаленному компьютеру.

Если ваша машина имеет только один внешний сетевой интерфейс, и этот интерфейс имеет только один IP-адрес, то этот IP-адрес обычно называют адресом машины, но это неточно.
Например, если машина подключена к VPN через виртуальный интерфейс, она будет использовать IP-адрес этого интерфейса для подключения к другой машине в VPN, а не внешний IP-адрес

Среди других решений: использует "Sys::Hostname"
(Работает, если Sys::Hostname имеет разрешаемое имя хоста)

use Sys::Hostname;
use Socket;
my($addr)=inet_ntoa((gethostbyname(hostname))[4]);
print "$addr\n";
6 голосов
/ 10 сентября 2012

Чтобы получить IP-адрес всех интерфейсов, используйте IO :: Interface :: Simple :

perl -MIO::Interface::Simple '-Esay $_->address for grep { $_->is_running && defined $_->address } IO::Interface::Simple->interfaces'

Если вас не интересует 127.0.0.1 (loopback), вы можете включить $_->is_loopback.

2 голосов
/ 09 ноября 2011

Perldoc имеет ответ на этот вопрос в своем FAQ ("perlfaq9") - с использованием различных модулей (которые являются частью стандартной библиотеки) или даже встроенной функции.

1 голос
/ 01 декабря 2008

У меня был хороший успех с IO :: Interface в Linux и Solaris, и я думаю, что он даже работал в AIX, но я не могу вспомнить наверняка. Просматривая search.cpan.org, rt.cpan.org и различные сайты ActiveState, похоже, что IO :: Interface может испытывать проблемы со сборкой в ​​Windows. Я думаю, что единственный способ узнать, доступен ли он, - это поиск io-интерфейса в PPM.

0 голосов
/ 29 января 2017

Я использовал комбинацию этих команд Linux, поэтому не зависел ни от одного модуля perl.

hostname -i
hostname -I
ls /sys/class/net
ip -f inet addr show eth0| grep -Po 'inet \K[\d.]+'
0 голосов
/ 25 февраля 2014

для окон я использую

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 не очень полезен.

0 голосов
/ 15 ноября 2011

Net :: Address :: IP :: Local работает нормально, но поскольку оригинальный плакат запрашивает все локальные адреса, я думаю, что этот лучше:

http://www.perlmonks.org/?node_id=166951

У меня с ActivePerl для Windows XP все работало нормально.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...