IP Addresse im lokalen Netz ermitteln...

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Wie kann man allgemeingültig die IP Addresse im lokalen Netz ermitteln?!?

Bei https://stackoverflow.com/questions/166 ... ons-stdlib gibt es einige Ansätze, aber die Ultimative Lösung scheint dabei nicht zu sein...

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@jens: diese Frage läßt sich nicht allgemeingültig beantworten. Was ist das lokale Netz? Ein Rechner kann mehrere reale oder virtuelle Netzwerkschnittstellen haben und für jede dieser Schnittstellen kann es keine oder mehrere gültige IP-Adressen geben (sowohl in IPv4- als auch IPv6-Ausführung). Die richtigste Antwort ist wohl das, was ifconfig liefert. Wahrscheinlich hat auch irgendwer schon ein Python-Modul geschrieben, das diese Information auswertet: https://pypi.python.org/pypi/netifaces/
dannyboy385
User
Beiträge: 39
Registriert: Freitag 27. November 2015, 21:24

Hey Leute. Ich bin mir sicher hier werden sich jetzt einigen die Haare streuben. Aber bei mir funktioniert diese kleine Klasse ganz gut. Die Antwort auf deine Frage wäre own_ip

Code: Alles auswählen

import os
import subprocess
import socket
class network():

	def connect(port,ip,timeout=3):
		'''Connect to an IP and Port und return Data recieved from it. Timeout kann be set'''
		try:
			connection=socket.socket() #connection.timeout(int(timeout))
			connection.connect((ip,int(port)))
			data=connection.recv(1024)
			connection.close()
			return data
		except socket.gaierror:
			return("no connection")

	def pingit(ip,timeout=3):
		'''Returns the result of an single ping to ip. You kann set timeout via parameter timeout.Returns False if reachable'''
		try:
			data=os.system("ping -c 1 -w "+str(timeout)+" "+str(ip))
			return bool(data)
		except subprocess.CalledProcessError:
			return True
	def pingtime(ip, timeout=3):
		'''Returns the result of an ping to ip.you can set timeout. '''
		try:
			data=subprocess.check_output("ping -c 1 -w "+str(timeout)+" "+str(ip)+" |grep time=", shell=True)
			data=data.decode("utf-8")
			datalist=data.split()
			pingtime=''.join(map(str, datalist[-2:-1]))
			return pingtime
		except socket.gaierror:
			return ("no connection")
	def own_ip():
		connection=socket.socket()
		connection.connect(("google.de",int(80)))

		own=(connection.getsockname()[0])
		connection.close()
		return own
Wie gesagt euch wird es grausen.... Aber es funktioniert. Ich habe es als network.py gespeichert und importiere es wenn ich eine derartige funktion benötige.

Mfg Daniel
PS: Verbesserungsvorschläge? Immer her damit :D :D
PS: Bitte Sirius erschlag mich nicht :D :D
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@dannyboy385: pro Ebene solltest Du mit 4 Leerzeichen einrücken, nach Funktionen eine Leerzeile. Zwischen Operatoren gehören auch Leerzeichen. network ist für eine Klasse falsch geschrieben. connect erstellt keine Verbindung sondern liest Daten, in nicht deterministischer Form, Nutzen also sehr begrenzt. pingit liefert einen seltsamen Rückgabewert. os.system solltest Du nicht benutzen und die Exception, die Du darin abfängst, tritt nie auf. In pingtime solltest Du nicht shell=True verwenden. Der grep ist in Python einfacher zu realisieren. Was Du da mit split und join machst, wird mir auch nicht klar, jedenfalls liefert es keine Zeit zurück, sondern einen String. own_ip ist auch kein Name für eine Funktion, weil es keine Tätigkeit beschreibt. Insgesamt hast Du keine Klasse geschrieben, weil die Funktionen genausogut außerhalb einer Klasse stehen könnten. Allen Methoden fehlt ein self, das dann gar nicht benutzt würde.
dannyboy385
User
Beiträge: 39
Registriert: Freitag 27. November 2015, 21:24

Hallo sirius. Die einrückung entsthet durch ein mischmasch von Editoren die ich verwendet habe und hat mir auch schon so einige probleme bereitet. So wie es jetzt auf meiner PLatte ist funktioniert es.
Erklärung zu Pingit:
Erst hatte ich statt os.system
subprocess.check_call verwendet wo die exception auch auftreten könnte. Dar ich es auf einem Androiden verwendet hatte auf dem kein subprocess vorhanden war habe ich es auf os.system umgeschrieben.

pingtime liefert einen string der Form "21 ms" zurück. WEnn du Ping im Terminal ausführst wirst du sehen das die letzten "Elemente" der Zeile welche mit grep "gefiltert" wurde time=xx ms ist. Genau dieser Teil wird mit ''.join(map(str, datalist[-2:-1])) extrahiert. Für meine Verwendung reichte dieser String als ergebniss aus.

Wesshalb sollte ich shell=True nicht verwenden?
getownip wäre also die bessere wahl genauso wie pingip und pingtime habe ich das richtig interpretiert?

Ja die UFnktionen könnten Außerhalb stehen. Ich muss gestehen, dass mir das aber selbst erst gerade aufgefallen ist.
BlackJack

@dannyboy385: Die eigentliche Frage, *die* IP-Adresse im lokalen Netz zu ermitteln bekommt man mit `own_ip()` nicht gelöst weil es *die* lokale IP nicht geben muss. Und dass das ermitteln einer *lokalen* IP eine Internetverbindung und das Vorhandensein von google.de erfordert, ist nicht sinnvoll.

Was ``int(80)`` soll ist mir auch nicht ganz klar. Wird dann aus der Ganzzahl eine echt, tatsächlich, wirklich, 100%ige Ganzzahl, weil das vorher nur so ungefähr eine war, die Gefahr lief in einen Dezimalbruch abzugleiten? ;-)

Wie kommst Du darauf dass das weglassen der Unterstriche in Namen besser wäre? Damit werden die schwerer lesbar!

Wenn man ``shell=True`` verwendet hat man die gleichen Probleme aus denen man von `os.system()` die Finger lassen sollte.

Von dem ``''.join(map(str, datalist[-2:-1]))`` lass Dir einfach mal die ganzen Zwischenergebnisse ausgeben um zu sehen was das für ein Unsinn ist.
dannyboy385
User
Beiträge: 39
Registriert: Freitag 27. November 2015, 21:24

@BlackJack

JA gut das vorhanden sein von google ist aber mit unter sagen wir mal zu 99,999999% Sicherheit. :mrgreen: :mrgreen: :mrgreen:
Was ``int(80)`` soll ist mir auch nicht ganz klar. Wird dann aus der Ganzzahl eine echt, tatsächlich, wirklich, 100%ige Ganzzahl, weil das vorher nur so ungefähr eine war, die Gefahr lief in einen Dezimalbruch abzugleiten? ;-)
Sehr humorvolle aber doch sinnvolle Äusserung....Nun ja vllt war es ja doch ein Dezimalbruch der vermieden werden sollte. Zumal das ganze unter etlichen Alkoholeinfluss entstanden ist :D
Aber jetzt im ernst. Das int() als überflüssig zu bezeichnen ist durchaus berechtigt.

Nun ja das war ein Lösungsansatz mit google der jetzt im Nachhinein doch nicht einmal so gut ist. Nur die Frage ist wie löst man das Problem dann. Zu irgendwas muss bei dieser methode ja eine Verbindung aufgebaut werden und andere Ziele wie z.B der Wlan Router oder ähnliches sind so Allgemein nicht bekannt :K . Also ist dieser Lösungsansatz schon einmal zu verwerfen.

``''.join(map(str, datalist[-2:-1]))` :K
ist wirklich ein ziemlicher Umweg und allgemein wahrscheinlich auch für die wenigsten zu gebrauchen. Sinnvoller wäre eine Int in ms oder etwas ähnliches. :?:


Ich begebe mich schon einmal zum Galgen :mrgreen:
Ich muss sagen das es immer wieder sehr interessant ist was man doch als anfänger so alles falsch macht, und gut ist das man hier darauf hingewießen wird.

Nocheinmal zur Thematik der Klasse. Ich muss gestehen das ich immer noch nicht durch das konzept der OOP durchsteige. Traurig aber wahr. Das wurmt mich sehr, doch ich weis nicht wie ich das ganze noch in meinen SChädel bekommen sollte
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

dannyboy385 hat geschrieben:``''.join(map(str, datalist[-2:-1]))` :K
ist wirklich ein ziemlicher Umweg und allgemein wahrscheinlich auch für die wenigsten zu gebrauchen. Sinnvoller wäre eine Int in ms oder etwas ähnliches. :?:

Code: Alles auswählen

In [1]: range(10)
Out[1]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [2]: x = range(10)

In [3]: x[-2:-1]
Out[3]: [8]

In [4]: ''.join(map(str, x[-2:-1]))
Out[4]: '8'

In [5]: str(x[-2:-1])
Out[5]: '[8]'

In [6]: str(x[-2:-1][0])
Out[6]: '8'

In [7]: str(x[-2])
Out[7]: '8'
the more they change the more they stay the same
BlackJack

@dannyboy385: Um zu einem vorhandenen google.de zu kommen braucht man aber auch einen DNS-Server der das auflöst. Gerade letzte Woche hatte ich da beruflich bei einem deutschen Kabel- und Internetanbieter ein Problem mit dessen DNS erleben dürfen. So etwas sollte auf eine Funktion die eigentlich etwas lokales ermitteln soll, keinen Einfluss haben dürfen. Und es bleibt immer noch das Problem das die IP die da ermittelt wird, vielleicht eine andere ist, als die die man haben wollte.

OOP lernt man insbesondere *nicht* dadurch einfach alles irgendwie in Klassen zu stecken.
dannyboy385
User
Beiträge: 39
Registriert: Freitag 27. November 2015, 21:24

@BlackJack
Ich habe nun schon sehr viel rumexperimentiert und gelsen. Tutoriaks, Bücher, Allgemein Internet aber ich kriegs nicht in meinen schädel. Naja.
Das mit dem DNS server stimmt natürlich. Was heißt da eine andere als man haben wollte. Nach einigen Tests habe ich immer die korrekte "interne" IP Adresse geliefert bekommen. Nun ja. Es wird wohl wirklich bessere wege geben, wekche auch nicht zwangsläufig auf einem socket aufbauen müssen.
Es wöre sehr interessant hier eventuell zusammen eine Platformübergreifende möglichkeit dafür zu finden. Es würde dem Threadersteller und Ich dencke auch vielen anderen hier sehr nützlich sein.
BlackJack

@dannyboy385: Eine andere als man haben wollte heisst das ein Rechner mehr als eine IP-Adresse haben kann und auch in mehr als einem Netz hängen kann. Nimm ein Notebook das ein Netzwerkkabel eingestöpselt hat aber gleichzeitig auch per WLAN im Netz ist. Viele Plasterouter für zuhause bieten die Möglichkeit eines Gastnetzes und man möchte den File- oder Gameserver dann in das normale und in das Gastnetz hängen. Was wäre denn in solchen Fällen die richtige IP? Das kann der Rechner doch gar nicht wissen welche man da haben möchte, deswegen ist das Problem auch eines was man so allgemein gar nicht lösen kann per Programm. Es kommt auf das Netz an und auf den Zweck zu dem man die IP braucht.
tsaG
User
Beiträge: 14
Registriert: Samstag 22. August 2015, 00:20

Ich nutze dies hier, eventuell kann es ja jemand gebrauchen :)

Funktioniert unter Linux/Windows

Code: Alles auswählen

def get_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        # muss nicht unbedingt erreichbar sein
        s.connect(('10.255.255.255', 0))
        IP = s.getsockname()[0]
    except:
        IP = '127.0.0.1'
    finally:
        s.close()
    return IP
Grüße
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@tsaG: das ist keine Lösung. Wie schon weiter oben beschrieben, kann es verschiedene Routen zu unterschiedlichen Netzen geben. Diese haben auch unterschiedliche IP-Adressen. Bei Dir wird also die IP-Adresse ausgewählt, die zum Ziel 10.255.255.255 führt. Allgemein sollte man nie nackte excepts benutzen, da das das Debuggen unendlich kompliziert macht. Wähle immer die Exception aus, die Du erwartest, hier also socket.error.
Antworten