Estoy usando una secuencia de comandos Python para enviar paquetes UDP a un servidor que registrará mi secuencia de comandos para recibir notificaciones del servidor. El protocolo requiere que envíe mi propia dirección IP y el puerto en el que deseo recibir estas notificaciones, por lo que esta debería ser una dirección accesible desde la red del servidor.Python: obtenga la dirección IP local utilizada para enviar datos IP a una dirección IP remota específica
Las soluciones deben al menos funcionar en Windows XP y superior y preferiblemente Mac OS X, ya que esta es mi plataforma de desarrollo.
El primer paso es obtener la dirección IP de cualquiera de mis interfaces. Actualmente estoy usando el enfoque comúnmente sugerido para resolver el nombre de host propio de la máquina:
def get_local_address():
return socket.gethostbyname(socket.gethostname())
Esto solo funciona a veces. Actualmente devuelve 172.16.249.1
, que es la dirección de una interfaz virtual utilizada por VM Ware, por lo que este es un problema.
Mucho mejor sería una forma de obtener la dirección IP de la interfaz predeterminada, que debería ser la correcta la mayor parte del tiempo.
Aún mejor sería una forma de obtener la dirección IP real utilizada para conectarse al servidor mediante un protocolo orientado a la conexión como TCP. De hecho, me puedo conseguir esa dirección, pero no sin intentar abrir la conexión:
def get_address_to_connect_to(server_addr):
non_open_port = 50000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((server_addr, non_open_port))
except socket.error:
pass
else:
s.close() # just in case
return s.getsockname()[0]
Esto bloqueará hasta que un tiempo de espera de TCP se ha alcanzado en el caso de que el servidor es inalcanzable o un cortafuegos mal en el medio es el bloqueo de ICMP paquetes ¿Hay una mejor manera de obtener esa información?
¡Ah, dulce empatía! Con 'SOCK_DGRAM', ¡sería casi perfecto! Pero 's.getsockname()' returns '('0.0.0.0', 51770)' en mi caso. He intentado 's = socket.socket (socket.AF_INET, socket.SOCK_DGRAM); s.sendto (b'hello ', (' 1.2.3.4 ', 50000)); s.getsockname() [0] '. ¡Sería fantástico si añadieras tu código a tu respuesta! – Feuermurmel
Ver mis ediciones a la respuesta. – DNS
Eso funciona perfectamente; Incluso usa el [Discard Protocol] (http://en.wikipedia.org/wiki/Discard_Protocol) ¡No lo sabía! Reemplacé el 'del s' con una declaración' con'. – Feuermurmel