Modul socket

Python SELF DE
Level 24 , Lektion 1
Verfügbar

7.1 Was sind Sockets?

Lass uns noch tiefer graben. Zuerst haben wir gelernt, mit request zu arbeiten, dann mit http.client, dann mit Proxys. Was kommt als Nächstes? Dann schauen wir uns diese Bibliotheken unter der Haube an...

Ein Socket (wörtlich — Steckdose) ist ein Punkt im Netzwerk, über den Daten gesendet und empfangen werden. Ein Socket kann als Endpunkt eines bidirektionalen Kommunikationskanals zwischen zwei Programmen betrachtet werden, die auf derselben oder verschiedenen Maschinen laufen.

Sockets unterstützen verschiedene Netzwerkprotokolle, aber am häufigsten werden zwei verwendet:

  • TCP (Transmission Control Protocol): Zuverlässiges Protokoll, das die Verbindungseinrichtung, Datenintegritätsprüfung und die richtige Reihenfolge sicherstellt.
  • UDP (User Datagram Protocol): Ein verbindungsloses Protokoll, das keine Zustellung der Daten garantiert, aber schneller und effizienter für bestimmte Anwendungen ist.

Zur Identifizierung eines Sockets werden die IP-Adresse (zur Identifizierung des Geräts im Netzwerk) und der Port (zur Identifizierung einer bestimmten Anwendung oder eines Dienstes auf dem Gerät) verwendet.

Wichtig! Die IP-Adresse und der Port identifizieren ein Programm im Netzwerk eindeutig. Das ist wie eine Hausadresse und eine Wohnungsnummer. Die Hausadresse (IP-Adresse) ist die Adresse deines Computers im Netzwerk, und der Port ist die Wohnungsnummer, die das Programm verwendet, um Nachrichten zu empfangen und zu senden.

Mehr über die IP-Adresse und den Port erfährst du in den Vorlesungen über das Netzwerk.

Die Hauptschritte bei der Arbeit eines Programms mit Sockets:

  1. Erstellen eines Sockets: Das Programm erstellt einen Socket und gibt den Protokolltyp an (TCP oder UDP).
  2. Bind an eine Adresse: Der Socket wird mit einer IP-Adresse und einer Portnummer verbunden, um für Verbindungen oder das Senden/Empfangen von Daten verfügbar zu sein.
  3. Abhören und Verbindungsaufbau (für TCP):
    • Abhören: Der Server-Socket wird in den Abhörmodus versetzt, um eingehende Verbindungen zu erwarten.
    • Verbindungsaufbau: Der Client initiiert die Verbindung mit dem Server. Der Server akzeptiert die Verbindung und erstellt einen neuen Socket für die Interaktion mit dem Client.
  4. Datenübertragung: Daten werden zwischen Client und Server übertragen. Im Fall von TCP werden die Daten in einer zuverlässigen Reihenfolge übertragen.
  5. Verbindung schließen: Nach Abschluss des Datenaustauschs wird die Verbindung geschlossen.

Vorteile der Verwendung von Sockets:

  • Flexibilität: Sockets ermöglichen es Anwendungen, Daten auszutauschen, unabhängig von ihrem Standort und ihrer Plattform.
  • Leistung: Sockets bieten eine schnelle und effiziente Möglichkeit, Daten zu übertragen, besonders bei der Verwendung von UDP.
  • Zuverlässigkeit (im Falle von TCP): Das TCP-Protokoll stellt eine zuverlässige Datenübertragung mit Integritätsprüfung und Wiederherstellung verlorener Pakete sicher.

7.2 Erstellen eines Socket-Servers

Die Arbeit mit Sockets in Python erfolgt mit dem eingebauten Modul socket, das eine Schnittstelle für Low-Level-Netzwerkprogrammierung bietet.

Mit Sockets kannst du einen socket-server erstellen — eine Anwendung/Objekt, die Anfragen von Clients empfängt und beantwortet. Ebenso kannst du einen socket-client erstellen — eine Anwendung/Objekt, die Anfragen an den socket-server sendet und Antworten von ihm erhält.

Um einen socket-server zu erstellen, führe drei Schritte aus:

  1. Erstelle ein Socket-Server-Objekt.
  2. Verbinde (bind) es mit einer IP-Adresse und einem Port.
  3. Aktiviere den Modus zum Abhören (listen) eingehender Nachrichten.

Dieser Code sieht ungefähr so aus:


import socket

# Erstellung eines Sockets
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
# Verbinden des Sockets mit einer Adresse und einem Port
server_socket.bind(('localhost', 12345))
    
# Abhören eingehender Verbindungen
server_socket.listen(5)
print("Server wartet auf eine Verbindung...")

Hier gibt socket.AF_INET an, dass wir IPv4 für das Netzwerkprotokoll verwenden, und socket.SOCK_STREAM bedeutet, dass wir TCP verwenden. Diese Parameter werden am häufigsten zum Erstellen von Netzwerk-Anwendungen verwendet.

Nachdem eine eingehende Nachricht eingegangen ist, müssen noch vier Schritte ausgeführt werden:

  1. Akzeptiere (accept) die Verbindung mit dem Client.
  2. Empfange (receive) die Anfrage (Daten) vom Client.
  3. Sende (send) eine Antwort — ebenfalls einige Daten — an den Client.
  4. Schließe (close) die Verbindung.

Dieser Code sieht ungefähr so aus:


# Akzeptieren einer neuen Verbindung
client_socket, client_address = server_socket.accept()
print(f"Verbindung hergestellt mit {client_address}")

# Empfang von Daten vom Client
data = client_socket.recv(1024)
print(f"Erhalten: {data.decode('utf-8')}")

# Senden von Daten an den Client
client_socket.sendall(b'Hallo, Client!')

# Schließen der Verbindung mit dem Client
client_socket.close()

Die Methode sendall() wird anstelle von send() verwendet, weil sie garantiert, dass alle Daten gesendet werden. Die Methode send() kann nur einen Teil der Daten senden, wenn der Puffer voll wird.

Die Zahl 1024 in recv(1024) gibt die maximale Anzahl von Bytes an, die gleichzeitig empfangen werden können. Das hilft, die Menge der Daten zu kontrollieren, die bei einer Operation verarbeitet werden.

Der Code des letzten Beispiels wird in der Regel in einer Endlosschleife ausgeführt — der Server verarbeitet eine Anfrage, wartet dann auf die nächste, verarbeitet diese und so weiter.

Wenn du ihn bei dir ausführen oder einfach das vollständige Beispiel sehen möchtest, füge ich es hier ein:


import socket

# Erstellung eines Sockets
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        
# Verbinden des Sockets mit einer Adresse und einem Port
server_socket.bind(('localhost', 12345))
        
# Abhören eingehender Verbindungen
server_socket.listen(5)
print("Server wartet auf eine Verbindung...")
        
while True:
    # Akzeptieren einer neuen Verbindung
    client_socket, client_address = server_socket.accept()
    print(f"Verbindung hergestellt mit {client_address}")
        
    # Empfang von Daten vom Client
    data = client_socket.recv(1024)
    print(f"Erhalten: {data.decode('utf-8')}")
        
    # Senden von Daten an den Client
    client_socket.sendall(b'Hallo, Client!')
        
    # Schließen der Verbindung mit dem Client
    client_socket.close()

7.3 Erstellen eines Socket-Clients

Wir haben einen Socket-Server erstellt, jetzt schreiben wir unseren Socket-Client, der den Server anfragt und Daten von ihm erhält.

Dazu müssen fünf Aktionen durchgeführt werden:

  1. Erstelle ein socket-client-Objekt.
  2. Stelle eine Verbindung (connect) mit der IP-Adresse und dem Port unseres socket-servers her.
  3. Sende (send) eine Nachricht an den Server.
  4. Empfange (receive) Daten vom Server.
  5. Schließe (close) die Verbindung.

Das ist eigentlich einfacher, als es scheint. So sieht dieser Code aus:


import socket

# Erstellung eines Sockets
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    
# Verbindung zum Server herstellen
client_socket.connect(('localhost', 12345))
    
# Senden von Daten an den Server
client_socket.sendall(b'Hallo, Server!')
    
# Empfang von Daten vom Server
data = client_socket.recv(1024)
print(f"Vom Server erhalten: {data.decode('utf-8')}")
    
# Schließen des Sockets
client_socket.close()

Wenn auf der anderen Seite kein socket-server läuft oder die Verbindung abbricht, tritt eine Ausnahme vom Typ socket.error auf. Vergiss also nicht, Ausnahmen zu behandeln.

Damit beenden wir heute unsere Arbeit mit Sockets.

Bei der Arbeit mit dem Netzwerk werden dir immer wieder Hosts, Ports, IP-Adressen, das Einrichten von Verbindungen, das Abhören von Anfragen und all das begegnen. Ein Verständnis dafür, wie es tief im Inneren funktioniert, erleichtert dir das Leben erheblich und hilft dir, verstreutes Wissen zu einem einheitlichen Bild zusammenzufügen.

Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION