Python: Holen Sie sich die lokale IP-Adresse zum senden von IP-Daten an eine bestimmte remote IP-Adresse
Bin ich mit einem Python-Skript zum senden von UDP-Paketen an einen server von registrieren mein script zum empfangen von Benachrichtigungen vom server. Das Protokoll verlangt, dass ich meine eigene IP-Adresse und port, auf dem ich empfangen möchten, diese Meldungen, so sollte dies eine Adresse sein, die vom server aus erreichbar ist Netzwerk.
Lösungen sollten zumindest die Arbeit auf Windows XP und höher und vorzugsweise Mac OS X, dies ist mein Entwicklungs-Plattform.
Der erste Schritt ist, um die IP-Adresse meiner Schnittstellen. Ich bin derzeit mit die häufigsten vorgeschlagene Ansatz zur Lösung des Maschinen eigenen host-Namen:
def get_local_address():
return socket.gethostbyname(socket.gethostname())
Dies funktioniert nur manchmal. Derzeit gibt es 172.16.249.1
, das ist die Adresse der virtuellen Schnittstelle verwendet, die durch VM-Ware, so ist dies ein problem.
Viel besser wäre ein Weg, um die IP-Adresse des Standard-Schnittstelle, die sollten die richtigen sein, die meisten der Zeit.
Noch besser wäre ein Weg, um die tatsächliche IP-Adresse verwendet, um die Verbindung zum server durch einen verbindungsorientierten Protokolls wie TCP. Ich kann wirklich erhalten Sie die Adresse, nicht aber, ohne beim öffnen der Verbindung:
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]
Diese blockieren, bis einige TCP-timeout wurde erreicht in dem Fall, dass der server nicht erreichbar ist oder eine böse firewall dazwischen ist die Blockierung von ICMP-Paketen. Gibt es einen besseren Weg, um diese Informationen zu erhalten?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich zu lösen hatte das gleiche problem einmal, und verbrachte viel Zeit mit dem Versuch, einen besseren Weg finden, ohne Erfolg. Ich begann auch mit gethostname, aber entdeckt, als Sie wusste, dass es nicht immer wieder das richtige Ergebnis, und kann auch eine Ausnahme in den Fällen, in denen es ein problem mit der hosts-Datei.
Die einzige Lösung, die ich finden konnte, die zuverlässig arbeitet über Plattformen hinweg ist zu versuchen, die Verbindung, wie du tust. Eine Verbesserung auf Ihrer code ist die Verwendung von UDP statt TCP, d.h. SOCK_DGRAM statt SOCK_STREAM. Das vermeidet die connect-timeout, und die Funktion nur sofort abgeschlossen.
Wenn Sie die Bereitstellung dieser code an client-Standorten, die möglicherweise ausgeführt werden, firewalls, stellen Sie sicher Sie dokumentieren die Tatsache, dass es nicht diese überprüfen. Sonst können Sie sehen, eine firewall-Warnung für eine ausgehende Verbindung auf port 50000, nicht seinen Zweck verstehen, und halte es für einen Fehler.
Edit: hier mal grob der code, den ich verwendet:
Ich glaube, du bist immer 0.0.0.0 weil Sie beim schließen der socket vor dem Aufruf getsockname. Ein weiterer Tipp ist die Nutzung von port 9; es ist die RFC863 UDP-discard-port, und daher etwas weniger komisch als einige zufällige high-nummerierten port.
SOCK_DGRAM
wäre es in der Nähe-perfekt! Abers.getsockname()
zurück('0.0.0.0', 51770)
in meinem Fall. Ich habe versuchts = socket.socket(socket.AF_INET, socket.SOCK_DGRAM); s.sendto(b'hello', ('1.2.3.4', 50000)); s.getsockname()[0]
. Es wäre großartig, wenn Sie Ihren code auf Ihre Antwort!del s
mit einemwith
- Anweisung.Übernimmt die entsendende Seite muss wissen, wie seine IP-Adresse?
Kann nicht der client einfach nur Zuhören, für die Daten abonnieren möchten (auf allen Schnittstellen) nach dem senden der UDP 'registrieren' und haben den server einfach starten Sie das senden der Daten an die Adresse, von dem das Datagramm stammt?
Contact
header einerREGISTER
Anfrage.