HOWTO · Python

So beheben Sie socket.gaierror: [Errno 8] nodename nor servname provided, or not known in Python

Diagnostizieren Sie Python socket.gaierror, indem Sie den Hostnamen, den Dienst, den Resolver und das Ziel des Clients überprüfen, und verifizieren Sie dann eine lokale Client-Server-Verbindung.

Auf dieser Seite

socket.gaierror: [Errno 8] nodename nor servname provided, or not known bedeutet, dass das System einen Namen oder Dienst, der bei einem Socket-Aufruf übergeben wurde, nicht auflösen konnte. Prüfen Sie zuerst den Hostnamen und den Port oder Dienstnamen. Stellen Sie anschließend sicher, dass die Adresse zum Standort des Servers passt. Wortlaut und Fehlernummer können je nach Betriebssystem und Resolver abweichen.

socket.gaierror und [Errno 8] verstehen

Python löst socket.gaierror aus, wenn eine Adressabfrage über den Systemresolver fehlschlägt. Der Hostname kann falsch geschrieben, für den konfigurierten Resolver nicht verfügbar oder nicht angegeben sein. Auch der Dienstwert kann fehlen oder nicht unterstützt werden. Der angezeigte Text zu [Errno 8] ist plattformabhängig. Prüfen Sie daher die Eingaben und den Resolver, statt sich auf genau diese Fehlernummer zu verlassen.

Den Fehler mit einer Hostnamenabfrage reproduzieren

Mit socket.getaddrinfo() können Sie dieselben Host- und Dienstwerte prüfen, die Ihre Anwendung beim Verbindungsaufbau an den Client übergibt. Dieses Beispiel gibt bei erfolgreicher Abfrage die Anzahl möglicher Adressen aus und zeigt bei einem Fehler die Meldung des Resolvers an. Es verwendet localhost und lässt sich daher ohne einen öffentlichen DNS-Namen ausprobieren.

import socket

hostname = "localhost"
service = "http"

try:
    addresses = socket.getaddrinfo(hostname, service, type=socket.SOCK_STREAM)
except socket.gaierror as error:
    print(f"Could not resolve {hostname}:{service}: {error}")
else:
    print(f"Resolved {hostname}:{service} to {len(addresses)} address candidate(s)")

Hostnamen und Dienst prüfen

Geben Sie als Host einen Hostnamen oder eine IP-Adresse und als Dienst einen Port oder einen anerkannten Dienstnamen an. Übergeben Sie keine vollständige URL wie https://example.com/path: Schema und Pfad gehören nicht zum Socket-Host. Prüfen Sie außerdem auf Leerzeichen, Tippfehler und Werte, die vor dem Verbindungsaufruf leer werden. socket.gethostname() gibt den konfigurierten Hostnamen des lokalen Rechners zurück. Das garantiert weder, dass ein anderer Rechner diesen Namen auflösen kann, noch dass es der gewünschte Server ist.

DNS- und Netzwerkauflösung diagnostizieren

Wenn socket.getaddrinfo() bei einem entfernten Hostnamen fehlschlägt, versuchen Sie, denselben Namen mit den üblichen Netzwerkdiagnosewerkzeugen des Betriebssystems aufzulösen, und prüfen Sie den konfigurierten Resolver des Rechners. Vergleichen Sie das Ergebnis bei Bedarf mit einem bekannten Hostnamen, aber nur als Diagnose: Wird ein Name aufgelöst, bedeutet das nicht, dass alle Namen auflösbar sind. DNS-Abfrage und Aufbau einer Netzwerkverbindung sind getrennte Schritte. Eine fehlgeschlagene Verbindung allein belegt nicht, dass kein Internetzugang verfügbar ist. Firewalls, Routing und ein nicht gestarteter Server können Verbindungsversuche beeinträchtigen, nachdem die Namensauflösung erfolgreich war.

socket.setdefaulttimeout() legt für bestimmte Socket-Operationen einen Standard-Timeout fest. Die Funktion wählt keinen DNS-Server aus und setzt auch nicht zuverlässig einen Timeout für die systemweite Namensauflösung. Konfigurieren Sie DNS über das Betriebssystem oder die Netzwerkumgebung, nicht durch Ändern eines Python-Socket-Standards.

Die vom Client verwendete Adresse korrigieren

Befinden sich Server und Client auf demselben Rechner, binden Sie den Server an 127.0.0.1 und verbinden Sie den Client mit derselben Adresse. localhost ist ebenfalls ein lokaler Loopback-Name. Diese Adressen erreichen keinen Server auf einem anderen Rechner. Ein entfernter Client benötigt den erreichbaren Hostnamen oder die IP-Adresse des Servers, und der Server muss an einer Schnittstelle lauschen, die von diesem Client erreichbar ist.

Das folgende vollständige Beispiel startet einen kleinen lokalen Server, sendet eine Nachricht und gibt die Antwort aus. Es zeigt, wie lokale Bind-Adresse und Client-Zieladresse übereinstimmen.

import socket
import threading

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server:
    server.bind(("127.0.0.1", 0))
    server.listen()
    host, port = server.getsockname()

    def respond():
        with server.accept()[0] as connection:
            message = connection.recv(1024)
            connection.sendall(b"received: " + message)

    worker = threading.Thread(target=respond)
    worker.start()

    with socket.create_connection((host, port)) as client:
        client.sendall(b"ping")
        print(client.recv(1024).decode("ascii"))

    worker.join()

Verbindung überprüfen

Prüfen Sie zuerst mit socket.getaddrinfo(), ob Host und Dienst aufgelöst werden. Kontrollieren Sie anschließend, ob der Server an der erwarteten Schnittstelle und am erwarteten Port lauscht, und verbinden Sie sich über eine Adresse, die vom Client erreichbar ist. Im lokalen Beispiel wählt der Server einen verfügbaren Port, den der Client anschließend ebenfalls verwendet. Ein öffentlicher DNS-Eintrag oder ein externer Dienst ist daher nicht erforderlich. Prüfen Sie bei einer entfernten Verbindung Serveradresse, lauschende Schnittstelle, Firewall-Regeln und Port jeweils separat. Eine erfolgreiche Abfrage bestätigt die Namensauflösung; eine erfolgreiche Verbindung bestätigt, dass bei diesem Versuch ein Listener erreichbar war.