Seite 1 von 1

Prüfen ob Internetverbindung vorhanen ist

Verfasst: Mittwoch 16. Juli 2008, 15:53
von nepi
Hi zusammen..

und wieder einmal nutze ich euer wissen gnadenlos aus.. :)

Ich habe mir eine Methode gebastelt, die anhand eines Pings testet, ob eine aktive Internetleitung vorhanden ist auf dem Rechner. Ich denke, mit einem Ping geht dies am schnellsten, andere Ideen??

Nun, mein 1 Versuch war dieser:

Code: Alles auswählen

def isConnectionOk():
    try:
        ret = call("ping www.google.com -n 2", stdout=-1, shell=True)
        if (ret):
            return 0
        else:
            return 1
    except:
        print "isConnectionOk: couldn't check internet connection"
        return 0 
Problem: Manchmal, wenn das Modem noch am resetten ist, schlug diese Methode fehl, sprich gab mir eine 1 zurück, obwohl noch *keine* Verbindung vorhanden war.

2. Versuch war:

Code: Alles auswählen

def isConnectionOk():
    pipe = Popen(('ping', 'www.google.ch'), stdout=PIPE)
    pingText = pipe.stdout.read()
    pipe.wait()
    
    if (pingText.find("Antwort von") > -1):
        return 1
    elif (pingText.find("Ping-Anforderung konnte Host") > -1):
        return 0
    else:
        return 0
Problem: Der stdout Text wird immer ausgegeben, egal was ich mache. Kann ich das verhindern? Möchte nicht in der console diesen output haben.
Sehe aber ein das ich den output des stdout brauche (-> pipe.stdout.read()). Aber vielleicht kann man den ja trotzdem abschalten?

vielen dank euch...

Verfasst: Mittwoch 16. Juli 2008, 16:11
von BlackJack
Auswertung des Rückgabecodes ist auf jeden Fall der Untersuchung des Textes vorzuziehen. Denn nicht jedes `ping` "antwortet" auf deutsch. Und selbst wenn man die Sprache kennt, kann sich der Text bei verschiedenen `ping`-Implementierungen unterscheiden.

Verfasst: Mittwoch 16. Juli 2008, 16:13
von nepi
aber wie stelle ich das in diesem Beispiel am besten an? Das 1. Codebeispiel war wie gesagt zu wenig genau, das hat mir aber immerhin rückgabecodes gegeben...

Verfasst: Mittwoch 16. Juli 2008, 17:36
von lunar
Der Rückgabewert eines erfolgreichen Kommandos ist 0, nicht 1 und "subprocess.call" gibt keine bool'schen Werte zurück! Dein Test im ersten Versuch ist also genau verkehrt herum. Dazu kommt noch, dass beim "shell=True" der Rückgabewert der Subshell zurückgegeben wird, der nicht notwendigerweise mit dem des aufgerufenen Kommandos identisch sein muss.

Richtig wäre folglich folgendes:

Code: Alles auswählen

retval = subprocess.call(['ping', '-n', '2', stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
if retval == 0:
    print "google alive"
else:
    print "google dead"
Noch eleganter ist übrigens "check_call", welches eine Ausnahme auslöst, wenn der Rückgabewert nicht gleich 0 ist. Dadurch wird der Zweck imho deutlicher:

Code: Alles auswählen

try:
    subprocess.check_call(['ping', '-n', '2', stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
    print 'google alive'
except subprocess.CalledProcessError:
    print 'google dead'
except EnvironmentError, err:
    print 'error when pinging:', err
Noch ein paar generelle Anmerkungen zum Code.
Integer nicht als boolsche Konstanten missbrauchen (True und False existieren), keine magischen Nummern verwenden (statt "stdout=-1" "stdout=subprocess.PIPE"), "shell=True" nur einsetzen, wenn eine Shell gewünscht ist, niemals ein except ohne konkrete Ausnahme, dass den Traceback verschluckt, PEP 8 bei Namen einhalten!

Verfasst: Mittwoch 16. Juli 2008, 17:57
von nepi
super... vielen dank für deine hilfestellung!
werde die dinge gleich mal ausprobieren... habe in der zwischen zeit leider ein neues problem mit pickles... habe ein neuer thread aufgemacht...

Verfasst: Mittwoch 16. Juli 2008, 18:21
von jens
Warum nicht einfach mit [mod]urllib[/mod] eine Seite abrufen, statt ein externes ping zu verwenden. Mit dabei noch ein socket timeout z.B. auf 1 oder 2 setzten.

ping gibt's auch in Python, als externes Modul z.B.: http://trac.pylucid.net/browser/CodeSnippets/ping.py

Nachteil: Muß als root/Administrator laufen...

Verfasst: Mittwoch 16. Juli 2008, 20:41
von lunar
@nepi
Warum willst du eigentlich wissen, ob die Internetverbindung steht? In einer Anwendung ist das ziemlich unsinnig, weil man anstelle des Pings auch einfach gleich den Verbindungsaufbau versuchen kann. Sprich, anstelle vorher per ping zu gucken, ob Google lebt, und dann einen HTTP Request zu starten, kann ich den Request auch gleich abschicken. Das spart Traffic und öffnet vor allem keine Race Conditions.
jens hat geschrieben:Warum nicht einfach mit [mod]urllib[/mod] eine Seite abrufen, statt ein externes ping zu verwenden. Mit dabei noch ein socket timeout z.B. auf 1 oder 2 setzten.
Da würde ich lieber schnell was eigenes bauen, dass nur "HEAD" sendet. Man muss ja nicht zu viel Traffic verschwenden.

Code: Alles auswählen

from __future__ import with_statement
from contextlib import closing
import socket

def http_ping(server, port=80):
    try:
        with closing(socket.socket()) as sock:
            sock.settimeout(1)
            sock.connect((server, port))
            sock.send('HEAD / HTTP/1.0\r\n\r\n')
            return sock.recv(10).startswith('HTTP/1.0')
    except (socket.error, socket.gaierror, socket.timeout):
        return False
Um festzustellen, ob eine Internetverbindung besteht, reicht es aber eigentlich, einen beliebigen Port auf dem Zielhost abzufragen, und auf "socket.timeout" oder "socket.gaierror" zu reagieren. Diese Fehler signalisieren in der Regel ein Fehlschlagen des Verbindungsaufbaus. Ein "Connection refused" nämlich bedeutet ebenfalls, dass der Server lebt.

Der Vorteil an pings ist halt, dass man sie in schneller Folge senden kann, weil kein TCP-Handshake erforderlich ist, sondern nur ein Paket gesendet wird. Das ist in der Regel schneller als ein HTTP Ping.
Nachteil: Muß als root/Administrator laufen...
Unter Linux reicht CAP_NET_RAW, UID 0 ist nicht erforderlich.

Verfasst: Mittwoch 16. Juli 2008, 23:52
von Leonidas
Ich habe es glaube ich beim letzten Usertreffen erwähnt, dass wenn www.google.com irgendwann nicht auf Pings antwortet einige tausend Programme denken werden, dass sie offline sind.

Mich würde doch durchaus interessieren wie viele tausend ICMP Pings pro Tag bei Google aufschlagen um zu checken ob Google noch da ist, ahem, ob man online ist.

Verfasst: Donnerstag 17. Juli 2008, 05:39
von BlackJack
Gleiches gilt wohl für heise.de -- ich weiss jedenfalls, dass ich nicht der einzige bin, der die anpingt, um mal schnell manuell zu prüfen ob's Netz da ist. :-)

Verfasst: Donnerstag 17. Juli 2008, 07:55
von Rebecca
Hehe, die domains am-i-online.[com|org] waeren noch frei... :D

Verfasst: Donnerstag 17. Juli 2008, 10:46
von audax
BlackJack hat geschrieben:Gleiches gilt wohl für heise.de -- ich weiss jedenfalls, dass ich nicht der einzige bin, der die anpingt, um mal schnell manuell zu prüfen ob's Netz da ist. :-)
Ist einfach kürzer als google.de ;)

Verfasst: Donnerstag 17. Juli 2008, 11:06
von BlackJack
Und man weiss ja auch nicht, was der Datenkrake Google mit den registrierten Pinganfragen macht. Vielleicht suchen die ja irgend wann einmal per Datamining nach Terroristen und ich habe zufällig ein auffälliges "Pingmuster". =:o)

Verfasst: Donnerstag 17. Juli 2008, 12:19
von lunar
Rebecca hat geschrieben:Hehe, die domains am-i-online.[com|org] waeren noch frei... :D
Eigentlich müsste man die registrieren und eine Seite ausliefern: "No!"

Verfasst: Donnerstag 17. Juli 2008, 12:27
von Leonidas
lunar hat geschrieben:
Rebecca hat geschrieben:Hehe, die domains am-i-online.[com|org] waeren noch frei... :D
Eigentlich müsste man die registrieren und eine Seite ausliefern: "No!"
Oder einfach Pings ignorieren ;)