Поиск локальных IP-адресов с использованием stdlib Python под Debian jessie
Я пишу программу распределенных систем на Python, и в этой программе мне нужно знать локальный IP-адрес... например. 168.192.... 10.13..... и т. Д., А не 127.0.0.1 или имя хоста.
Я нашел следующее решение на стеке потока
https://stackoverflow.com/questions/166506/finding-local-ip-addresses-using-pythons-stdlib
import socket
socket.gethostbyname(socket.gethostname())
Когда я запускаю это на своем ноутбуке Debian jessie, я получаю 127.0.0.1, однако мой друг, который использует Fedora на своем компьютере, получает желаемый IP-адрес, когда он запускает тот же сценарий (например, 168.192..)
Я предпочитаю использовать приведенное выше решение, если возможно, чтобы получить локальный IP-адрес, потому что большинство других предлагаемых решений - либо хаки, либо невероятно длинные...
Есть ли что-то, что я могу настроить на своем ноутбуке Debian jessie, чтобы python возвращал правильный локальный IP-адрес?
- используя Debian Джесси
- питон 3
- подключен к сети (.. и компьютер включен)...;)
- / etc / hosts в настоящее время содержит:
127.0.0.1 localhost
127.0.0.1 debianASUS
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
2 ответа
Самый надежный способ узнать IP-адрес, который ваш хост будет использовать для связи, это использовать getsockname
на подключенном сокете UDP. В случае UDP connect
Системный вызов не предполагает никакой сетевой связи.
Вот функция Python, которую я написал в прошлом для аналогичной цели. Если вы заранее не знаете, с каким удаленным IP-адресом вы будете связываться, вам следует искать тот, который будет использовать маршрут по умолчанию. Если вы уже знаете, с каким удаленным IP-адресом вы будете общаться, то лучше использовать этот IP-адрес в соединительном вызове.
def my_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect(('192.0.0.8', 1027))
except socket.error:
return None
return s.getsockname()[0]
С некоторыми незначительными изменениями эту функцию можно адаптировать для возврата адреса IPv6, а не IPv4:
def my_ipv6():
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
try:
s.connect(('2001:db8::', 1027))
except socket.error:
return None
return s.getsockname()[0]
Рассматривали ли вы возможность передачи решения конечному пользователю во время выполнения с помощью параметра конфигурации? Это стандартная практика для этой проблемы.
Причина в том, что не существует систематического надежного способа определения "локального" IP-адреса (хост может быть многосетевым, может работать с двойным стеком v4/v6, VPN и т. Д.). Конфигурация во время выполнения облегчит работу системного администратора!