it-swarm.com.de

Netzwerkverbindung überprüfen

Ich möchte sehen, ob ich auf eine Online-API zugreifen kann, aber dafür muss ich Internetzugang haben.

Wie kann ich mit Python feststellen, ob eine Verbindung verfügbar und aktiv ist?

101
aF.

Vielleicht könnten Sie so etwas verwenden:

import urllib2

def internet_on():
    try:
        urllib2.urlopen('http://216.58.192.142', timeout=1)
        return True
    except urllib2.URLError as err: 
        return False

Derzeit ist 216.58.192.142 eine der IP-Adressen für google.com. Ändern Sie http://216.58.192.142 auf die Website, von der erwartet wird, dass sie schnell reagiert

Diese feste IP-Adresse wird nicht für immer auf google.com abgebildet. Daher ist dieser Code Nicht robust - er muss ständig gewartet werden, damit er funktioniert. 

Der Grund, warum der obige Code eine feste IP-Adresse anstelle eines vollqualifizierten Domänennamens (FQDN) verwendet, liegt darin, dass ein FQDN eine DNS-Suche erfordern würde. Wenn der Computer über keine Internetverbindung verfügt, kann der DNS-Lookup den Aufruf von urllib_request.urlopen für mehr als eine Sekunde blockieren. Vielen Dank an @rzetterberg für diesen Hinweis.


Wenn die feste IP-Adresse oben nicht funktioniert, können Sie eine aktuelle IP-Adresse für google.com (unter Unix) finden, indem Sie sie ausführen

% Dig google.com  +trace 
...
google.com.     300 IN  A   216.58.192.142
112
unutbu

Wenn wir uns mit einem Internet-Server verbinden können, haben wir tatsächlich Konnektivität. Für den schnellsten und zuverlässigsten Ansatz sollten jedoch alle Lösungen mindestens die folgenden Anforderungen erfüllen:

  • Vermeiden Sie die DNS-Auflösung (wir benötigen eine IP-Adresse, die bekannt ist und für die meiste Zeit garantiert verfügbar ist)
  • Vermeiden Sie Verbindungen auf Anwendungsebene (Verbindung zu einem HTTP/FTP/IMAP-Dienst)
  • Vermeiden Sie Aufrufe externer Dienstprogramme von Python oder einer anderen Sprache Ihrer Wahl (wir müssen eine sprachunabhängige Lösung entwickeln, die nicht auf Lösungen von Drittanbietern angewiesen ist).

Um diesen Anforderungen zu entsprechen, besteht eine Möglichkeit darin, zu prüfen, ob einer der öffentlichen DNS-Server von Google erreichbar ist. Die IPv4-Adressen für diese Server sind 8.8.8.8 und 8.8.4.4. Wir können versuchen, eine Verbindung zu ihnen herzustellen.

Ein kurzer Nmap des Hosts 8.8.8.8 ergab folgendes Ergebnis:

$ Sudo nmap 8.8.8.8

Starting Nmap 6.40 ( http://nmap.org ) at 2015-10-14 10:17 IST
Nmap scan report for google-public-dns-a.google.com (8.8.8.8)
Host is up (0.0048s latency).
Not shown: 999 filtered ports
PORT   STATE SERVICE
53/tcp open  domain

Nmap done: 1 IP address (1 Host up) scanned in 23.81 seconds

Wie wir sehen können, ist TCP/53 offen und nicht gefiltert. Wenn Sie kein Root-Benutzer sind, denken Sie daran, Sudo oder das -Pn-Argument für Nmap zu verwenden, um erstellte Testpakete zu senden und festzustellen, ob der Host aktiv ist.

Bevor wir mit Python versuchen, testen wir die Konnektivität mit einem externen Tool, Netcat:

$ nc 8.8.8.8 53 -zv
Connection to 8.8.8.8 53 port [tcp/domain] succeeded!

Netcat bestätigt, dass wir 8.8.8.8 über TCP/53 erreichen können. Jetzt können wir in Python eine Socketverbindung zu 8.8.8.8:53/TCP einrichten, um die Verbindung zu überprüfen:

>>> import socket
>>>
>>> def internet(Host="8.8.8.8", port=53, timeout=3):
...   """
...   Host: 8.8.8.8 (google-public-dns-a.google.com)
...   OpenPort: 53/tcp
...   Service: domain (DNS/TCP)
...   """
...   try:
...     socket.setdefaulttimeout(timeout)
...     socket.socket(socket.AF_INET, socket.SOCK_STREAM).connect((Host, port))
...     return True
...   except Exception as ex:
...     print ex.message
...     return False
...
>>> internet()
True
>>>

Ein anderer Ansatz könnte darin bestehen, einen manuell erstellten DNS-Test an einen dieser Server zu senden und auf eine Antwort zu warten. Aber ich nehme an, es könnte sich im Vergleich aufgrund von Paketabstürzen, DNS-Auflösungsfehlern usw. als langsamer erweisen. Bitte kommentieren Sie, wenn Sie anders denken.

UPDATE # 1: Dank des Kommentars von @theamk ist Timeout jetzt ein Argument und standardmäßig mit 3s initialisiert.

UPDATE # 2: Ich habe schnelle Tests durchgeführt, um die schnellste und allgemeinste Implementierung aller gültigen Antworten auf diese Frage zu ermitteln. Hier ist die Zusammenfassung:

$ ls *.py | sort -n | xargs -I % sh -c 'echo %; ./timeit.sh %; echo'
defos.py
True
00:00:00:00.487

iamaziz.py
True
00:00:00:00.335

ivelin.py
True
00:00:00:00.105

jaredb.py
True
00:00:00:00.533

kevinc.py
True
00:00:00:00.295

unutbu.py
True
00:00:00:00.546

7h3rAm.py
True
00:00:00:00.032

Und noch einmal:

$ ls *.py | sort -n | xargs -I % sh -c 'echo %; ./timeit.sh %; echo'
defos.py
True
00:00:00:00.450

iamaziz.py
True
00:00:00:00.358

ivelin.py
True
00:00:00:00.099

jaredb.py
True
00:00:00:00.585

kevinc.py
True
00:00:00:00.492

unutbu.py
True
00:00:00:00.485

7h3rAm.py
True
00:00:00:00.035

True in der obigen Ausgabe bedeutet, dass alle diese Implementierungen der jeweiligen Autoren die Verbindung zum Internet richtig identifizieren. Die Zeit wird in Millisekunden Auflösung angezeigt.

UPDATE # 3: Nach Änderung der Ausnahmebehandlung erneut getestet:

defos.py
True
00:00:00:00.410

iamaziz.py
True
00:00:00:00.240

ivelin.py
True
00:00:00:00.109

jaredb.py
True
00:00:00:00.520

kevinc.py
True
00:00:00:00.317

unutbu.py
True
00:00:00:00.436

7h3rAm.py
True
00:00:00:00.030
73
7h3rAm

Es wird schneller sein, einfach eine HEAD -Anfrage zu stellen, damit kein HTML-Code abgerufen wird.
Auch ich bin sicher, dass Google es auf diese Weise besser haben möchte:)

try:
    import httplib
except:
    import http.client as httplib

def have_internet():
    conn = httplib.HTTPConnection("www.google.com", timeout=5)
    try:
        conn.request("HEAD", "/")
        conn.close()
        return True
    except:
        conn.close()
        return False
46
Ivelin

Um zu aktualisieren, was unutbu für neuen Code in Python 3.2 gesagt hat

def check_connectivity(reference):
    try:
        urllib.request.urlopen(reference, timeout=1)
        return True
    except urllib.request.URLError:
        return False

Um nur zu beachten, die Eingabe (Referenz) ist die URL, die Sie überprüfen möchten: Ich schlage vor, etwas auszuwählen, das sich schnell mit Ihrem Wohnort verbindet - dh ich wohne in Südkorea, also würde ich wahrscheinlich auf http verweisen : //www.naver.com .

16
Kevin C

Als Alternative zu den Antworten von ubutnu/Kevin C verwende ich das Paket requests wie folgt:

import requests

def connected_to_internet(url='http://www.google.com/', timeout=5):
    try:
        _ = requests.get(url, timeout=timeout)
        return True
    except requests.ConnectionError:
        print("No internet connection available.")
    return False

Bonus: Dies kann auf diese Funktion erweitert werden, die eine Website anpingt.

def web_site_online(url='http://www.google.com/', timeout=5):
    try:
        req = requests.get(url, timeout=timeout)
        # HTTP errors are not raised by default, this statement does that
        req.raise_for_status()
        return True
    except requests.HTTPError as e:
        print("Checking internet connection failed, status code {0}.".format(
        e.response.status_code))
    except requests.ConnectionError:
        print("No internet connection available.")
    return False
14
Def_Os

Sie können einfach versuchen, Daten herunterzuladen, und wenn die Verbindung fehlschlägt, wissen Sie, dass etwas mit Verbindung nicht in Ordnung ist.

Grundsätzlich können Sie nicht überprüfen, ob der Computer mit dem Internet verbunden ist. Es gibt viele Fehlerursachen, z. B. falsche DNS-Konfiguration, Firewalls oder NAT. Selbst wenn Sie einige Tests durchführen, können Sie nicht garantiert haben, dass Sie eine Verbindung mit Ihrer API haben, bis Sie es versuchen.

9
Tomasz Wysocki
import urllib

def connected(Host='http://google.com'):
    try:
        urllib.urlopen(Host)
        return True
    except:
        return False

# test
print( 'connected' if connected() else 'no internet!' )

Verwenden Sie für Python 3 urllib.request.urlopen(Host)

6
Aziz Alto

Versuchen Sie es trotzdem mit der Operation, die Sie versucht haben. Wenn dies fehlschlägt, sollte Python eine Ausnahme auslösen, um Sie darüber zu informieren.

Wenn Sie zunächst eine triviale Operation durchführen möchten, um eine Verbindung zu erkennen, führt dies zu einer Race-Bedingung. Was ist, wenn die Internetverbindung gültig ist, wenn Sie testen, aber vor der eigentlichen Arbeit ausfallen?

3
mluebke

Am besten versuchen Sie dies mit einer IP-Adresse zu überprüfen, die Python immer angibt, wenn die Website nicht gefunden wird. In diesem Fall ist dies mein Code:

import socket

print("website connection checker")
while True:
    website = input("please input website: ")
    print("")
    print(socket.gethostbyname(website))
    if socket.gethostbyname(website) == "92.242.140.2":
        print("Website could be experiencing an issue/Doesn't exist")
    else:
        socket.gethostbyname(website)
        print("Website is operational!")
        print("")
1
lunar_kitsune

Hier ist meine Version

import requests

try:
    if requests.get('https://google.com').ok:
        print("You're Online")
except:
    print("You're Offline")
1
Mujeeb Ishaque

Dies funktioniert möglicherweise nicht, wenn der localhost von 127.0.0.1.__ geändert wurde. Versuchen Sie es 

import socket
ipaddress=socket.gethostbyname(socket.gethostname())
if ipaddress=="127.0.0.1":
    print("You are not connected to the internet!")
else:
    print("You are connected to the internet with the IP address of "+ ipaddress )

Wenn nicht bearbeitet, lautet die IP-Adresse des Computers 127.0.0.1, wenn keine Verbindung zum Internet besteht. Dieser Code ruft im Wesentlichen die IP-Adresse ab und fragt, ob es sich um die localhost-IP-Adresse handelt

1
Steven Parkling

Ausgehend von der Antwort von unutbu als Ausgangspunkt und in der Vergangenheit durch das Ändern einer "statischen" IP-Adresse gebrannt worden, habe ich eine einfache Klasse erstellt, die einmal mit Hilfe eines DNS-Lookups prüft (dh mit der URL " https://www.google.com ")) und speichert dann die IP-Adresse des antwortenden Servers für nachfolgende Prüfungen. Auf diese Weise ist die IP-Adresse immer auf dem neuesten Stand (vorausgesetzt, die Klasse wird mindestens alle paar Jahre neu initialisiert). Ich gebe gawry auch Anerkennung für diese Antwort , die mir zeigte, wie man die IP-Adresse des Servers erhält (nach jeder Umleitung usw.). Bitte ignorieren Sie die offensichtliche Hässlichkeit dieser Lösung. Ich möchte hier ein minimales Arbeitsbeispiel nennen. :)

Folgendes habe ich:

import socket

try:
    from urllib2 import urlopen, URLError
    from urlparse import urlparse
except ImportError:  # Python 3
    from urllib.parse import urlparse
    from urllib.request import urlopen, URLError

class InternetChecker(object):
    conn_url = 'https://www.google.com/'

    def __init__(self):
        pass

    def test_internet(self):
        try:
            data = urlopen(self.conn_url, timeout=5)
        except URLError:
            return False

        try:
            Host = data.fp._sock.fp._sock.getpeername()
        except AttributeError:  # Python 3
            Host = data.fp.raw._sock.getpeername()

        # Ensure conn_url is an IPv4 address otherwise future queries will fail
        self.conn_url = 'http://' + (Host[0] if len(Host) == 2 else
                                     socket.gethostbyname(urlparse(data.geturl()).hostname))

        return True

# Usage example
checker = InternetChecker()
checker.test_internet()
0
Jared B.

Das funktioniert bei mir in Python3.6

import urllib
from urllib.request import urlopen


def is_internet():
    """
    Query internet using python
    :return:
    """
    try:
        urlopen('https://www.google.com', timeout=1)
        return True
    except urllib.error.URLError as Error:
        print(Error)
        return False


if is_internet():
    print("Internet is active")
else:
    print("Internet disconnected")
0
Rajiv Sharma

Ich nehme die Antwort von Ivelin und füge einige zusätzliche Überprüfungen hinzu, da mein Router seine IP-Adresse 192.168.0.1 liefert und einen Kopf zurückgibt, wenn er bei der Abfrage von google.com keine Internetverbindung hat.

def haveInternet():
    try:
        # first check if we get the correct IP-Address or just the router's IP-Address
        info = socket.getaddrinfo("www.google.com", None)[0]
        ipAddr = info[4][0]
        if ipAddr == "192.168.0.1" :
            return False
    except:
        return False

    conn = httplib.HTTPConnection("www.google.com", timeout=5)
    try:
        conn.request("HEAD", "/")
        conn.close()
        return True
    except:
        conn.close()
        return False
0
monok

Wenn ich die Antwort von Six nehme, denke ich, könnten wir uns irgendwie vereinfachen, ein wichtiges Thema, da Neuankömmlinge in sehr technischen Fragen verloren gehen.

Hier werde ich endlich einmal warten, bis meine Verbindung (3G, langsam) für meine PV-Überwachung hergestellt wird.

Funktioniert unter Pyth3 mit Raspbian 3.4.2

from urllib.request import urlopen
from time import sleep
urltotest=http://www.lsdx.eu             # my own web page
nboftrials=0
answer='NO'
while answer=='NO' and nboftrials<10:
    try:
        urlopen(urltotest)
        answer='YES'
    except:
        essai='NO'
        nboftrials+=1
        sleep(30)       

maximale Laufzeit: 5 Minuten, wenn ich es in einer Stunde probiert habe, aber es ist ein weiteres Skript!

0
Seylione

mein Favorit, wenn Sie Skripts in einem Cluster ausführen oder nicht

import subprocess

def online(timeout):
    try:
        return subprocess.run(
            ['wget', '-q', '--spider', 'google.com'],
            timeout=timeout
        ).returncode == 0
    except subprocess.TimeoutExpired:
        return False

dies wird wget leise ausgeführt. Es wird nichts heruntergeladen, sondern geprüft, ob die angegebene Remote-Datei im Web vorhanden ist

0
neok