socket — socket-Modul

Dieses Modul bietet Zugriff auf die BSD-Socket-Schnittstelle.

Unterschied zu CPython

Aus Effizienz- und Konsistenzgründen implementieren Socket-Objekte in MicroPython direkt eine stream-Schnittstelle (dateiähnlich). In CPython müssen Sie einen Socket mit der Methode makefile() in ein dateiähnliches Objekt umwandeln. Diese Methode wird von MicroPython weiterhin unterstützt (ist aber wirkungslos), achten Sie daher darauf, sie zu verwenden, wo die Kompatibilität mit CPython wichtig ist.

Socket-Adressformat(e)

Das native Socket-Adressformat des socket-Moduls ist ein undurchsichtiger Datentyp, der von der Funktion getaddrinfo() zurückgegeben wird und zur Auflösung textueller Adressen (einschließlich numerischer Adressen) verwendet werden muss:

sockaddr = socket.getaddrinfo('www.micropython.org', 80)[0][-1]
# You must use getaddrinfo() even for numeric addresses
sockaddr = socket.getaddrinfo('127.0.0.1', 80)[0][-1]
# Now you can use that address
sock.connect(sockaddr)

Die Verwendung von getaddrinfo() ist die effizienteste (sowohl hinsichtlich Speicher als auch Rechenleistung) und portabelste Art, mit Adressen zu arbeiten.

Das socket-Modul bietet außerdem eine CPython-kompatible Möglichkeit, Adressen über Tupel anzugeben, wie unten beschrieben. Auf der OpenMV Cam ist das socket-Modul integriert; numerische Adressen können direkt im Tupelformat angegeben werden, Domainnamen müssen jedoch zuerst mit getaddrinfo() aufgelöst werden.

Zusammengefasst:

  • Verwenden Sie immer getaddrinfo(), um Hostnamen aufzulösen.

  • Die unten beschriebenen Tupeladressen können als Kurzform für numerische Adressen verwendet werden, für schnelle Hacks und interaktive Nutzung.

Tupel-Adressformat für das socket-Modul:

  • IPv4: (ipv4_address, port), wobei ipv4_address ein String mit einer numerischen IPv4-Adresse in Punktnotation ist, z. B. "8.8.8.8", und port eine ganzzahlige Portnummer im Bereich 1-65535. Domainnamen werden nicht als ipv4_address akzeptiert; lösen Sie sie zuerst mit getaddrinfo() auf.

  • IPv6: (ipv6_address, port, flowinfo, scopeid), wobei ipv6_address ein String mit einer numerischen IPv6-Adresse in Doppelpunktnotation ist, z. B. "2001:db8::1", und port eine ganzzahlige Portnummer im Bereich 1-65535. flowinfo muss 0 sein. scopeid ist der Schnittstellen-Scope-Bezeichner für linklokale Adressen. Domainnamen werden nicht als ipv6_address akzeptiert; lösen Sie sie zuerst mit getaddrinfo() auf.

Funktionen

socket.getaddrinfo(host: str, port: int, af: int = 0, type: int = 0, proto: int = 0, flags: int = 0, /) List[Tuple]

Übersetzt das Host-/Port-Argument in eine Folge von 5-Tupeln, die alle notwendigen Argumente zum Erstellen eines mit diesem Dienst verbundenen Sockets enthalten. Die Argumente af, type und proto (die dieselbe Bedeutung wie bei der Funktion socket haben) können verwendet werden, um zu filtern, welche Art von Adressen zurückgegeben wird. Wenn ein Parameter nicht angegeben oder null ist, können alle Adresskombinationen zurückgegeben werden (was eine Filterung auf der Benutzerseite erfordert).

Die resultierende Liste von 5-Tupeln hat die folgende Struktur:

(family, type, proto, canonname, sockaddr)

Das folgende Beispiel zeigt, wie man sich mit einer gegebenen URL verbindet:

s = socket.socket()
# This assumes that if "type" is not specified, an address for
# SOCK_STREAM will be returned, which may be not true
s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][-1])

Empfohlene Verwendung der Filterparameter:

s = socket.socket()
# Guaranteed to return an address which can be connect'ed to for
# stream operation.
s.connect(socket.getaddrinfo('www.micropython.org', 80, 0, SOCK_STREAM)[0][-1])

Unterschied zu CPython

CPython löst im Fehlerfall in dieser Funktion eine socket.gaierror-Ausnahme aus (eine Unterklasse von OSError). MicroPython hat kein socket.gaierror und löst direkt OSError aus. Beachten Sie, dass die Fehlernummern von getaddrinfo() einen eigenen Namensraum bilden und möglicherweise nicht mit den Fehlernummern aus dem Modul errno übereinstimmen. Um getaddrinfo()-Fehler zu unterscheiden, werden sie durch negative Zahlen dargestellt, während Standard-Systemfehler positive Zahlen sind (Fehlernummern sind über die Eigenschaft e.args[0] eines Ausnahmeobjekts zugänglich). Die Verwendung negativer Werte ist ein vorläufiges Detail, das sich in Zukunft ändern kann.

socket.inet_ntop(af: int, bin_addr: bytes) str

Konvertiert eine binäre Netzwerkadresse bin_addr der angegebenen Adressfamilie af in eine textuelle Darstellung:

>>> socket.inet_ntop(socket.AF_INET, b"\x7f\0\0\1")
'127.0.0.1'
socket.inet_pton(af: int, txt_addr: str) bytes

Konvertiert eine textuelle Netzwerkadresse txt_addr der angegebenen Adressfamilie af in eine binäre Darstellung:

>>> socket.inet_pton(socket.AF_INET, "1.2.3.4")
b'\x01\x02\x03\x04'

Konstanten

socket.AF_INET: int

IPv4-Adressfamilie.

socket.AF_INET6: int

IPv6-Adressfamilie.

socket.SOCK_STREAM: int

Stream-Socket-Typ (TCP).

socket.SOCK_DGRAM: int

Datagram-Socket-Typ (UDP).

socket.SOCK_RAW: int

Raw-Socket-Typ.

socket.IPPROTO_IP: int

Die IP-Protokollebene. Wird als level-Argument für setsockopt() zusammen mit den IP_*-Optionen verwendet.

socket.IPPROTO_TCP: int

Das TCP-Protokoll. Sie müssen dies nicht an socket übergeben (der Socket-Typ SOCK_STREAM wählt es automatisch aus); seine einzige tatsächliche Verwendung ist als level-Argument für setsockopt() zusammen mit den TCP_*-Optionen.

socket.SOL_SOCKET: int

Die Socket-Optionsebene. Wird als level-Argument für setsockopt() zusammen mit den SO_*-Optionen verwendet.

socket.SO_REUSEADDR: int

Erlaubt dem Socket, sich an eine Adresse/einen Port zu binden, der sich noch im Zustand TIME_WAIT befindet.

socket.SO_BROADCAST: int

Erlaubt das Senden von Datagrammen an eine Broadcast-Adresse.

socket.SO_KEEPALIVE: int

Aktiviert die periodische Übertragung von Keep-Alive-Proben auf einem verbundenen Socket.

socket.SO_SNDTIMEO: int

Sende-Timeout in Millisekunden, übergeben als value-Argument an setsockopt().

socket.SO_RCVTIMEO: int

Empfangs-Timeout in Millisekunden, übergeben als value-Argument an setsockopt().

socket.IP_ADD_MEMBERSHIP: int

Tritt einer Multicast-Gruppe bei. Eine setsockopt()-Option auf IPPROTO_IP-Ebene.

socket.IP_DROP_MEMBERSHIP: int

Verlässt eine Multicast-Gruppe. Eine setsockopt()-Option auf IPPROTO_IP-Ebene.

socket.TCP_NODELAY: int

Deaktiviert den Nagle-Algorithmus. Eine setsockopt()-Option auf IPPROTO_TCP-Ebene.

socket.MSG_PEEK: int

Für recv() / recvfrom(): gibt Daten zurück, ohne sie aus der Eingabewarteschlange zu entfernen.

socket.MSG_DONTWAIT: int

Für recv() / recvfrom(): führt die Operation im nicht-blockierenden Modus aus.

Klassen

class socket.socket(af: int = AF_INET, type: int = SOCK_STREAM, proto: int = IPPROTO_TCP, /)

Erstellt einen neuen Socket mit der angegebenen Adressfamilie, dem Socket-Typ und der Protokollnummer. Die Angabe von proto ist in den meisten Fällen nicht erforderlich (und nicht empfohlen); das type-Argument wählt das benötigte Protokoll automatisch aus:

# Create STREAM TCP socket
socket(AF_INET, SOCK_STREAM)
# Create DGRAM UDP socket
socket(AF_INET, SOCK_DGRAM)
close() None

Markiert den Socket als geschlossen und gibt alle Ressourcen frei. Sobald dies geschieht, schlagen alle zukünftigen Operationen am Socket-Objekt fehl. Das entfernte Ende erhält eine EOF-Anzeige, sofern dies vom Protokoll unterstützt wird.

Sockets werden beim Garbage-Collecting automatisch geschlossen, es wird jedoch empfohlen, sie mit close() explizit zu schließen, sobald Sie die Arbeit mit ihnen beendet haben.

bind(address: Any) None

Bindet den Socket an address. Der Socket darf noch nicht gebunden sein.

listen(backlog: int = 2) None

Ermöglicht einem Server, Verbindungen anzunehmen. Wenn backlog angegeben ist, muss es mindestens 0 sein (ist es niedriger, wird es auf 0 gesetzt) und gibt die Anzahl der nicht angenommenen Verbindungen an, die das System zulässt, bevor neue Verbindungen abgelehnt werden. Wenn nicht angegeben, wird ein vernünftiger Standardwert gewählt.

accept() Tuple['socket', Tuple]

Nimmt eine Verbindung an. Der Socket muss an eine Adresse gebunden sein und auf Verbindungen warten. Der Rückgabewert ist ein Paar (conn, address), wobei conn ein neues Socket-Objekt ist, das zum Senden und Empfangen von Daten über die Verbindung verwendet werden kann, und address die Adresse ist, die am anderen Ende der Verbindung an den Socket gebunden ist.

connect(address: Any) None

Stellt eine Verbindung zu einem entfernten Socket unter address her.

send(bytes: bytes) int

Sendet Daten an den Socket. Der Socket muss mit einem entfernten Socket verbunden sein. Gibt die Anzahl der gesendeten Bytes zurück, die kleiner als die Länge der Daten sein kann („short write“).

sendall(bytes: bytes) None

Sendet alle Daten an den Socket. Der Socket muss mit einem entfernten Socket verbunden sein. Im Gegensatz zu send() versucht diese Methode, alle Daten zu senden, indem sie die Daten Stück für Stück nacheinander sendet.

Das Verhalten dieser Methode bei nicht-blockierenden Sockets ist undefiniert. Daher wird in MicroPython empfohlen, stattdessen die Methode write() zu verwenden, die dieselbe „no short writes“-Richtlinie für blockierende Sockets hat und bei nicht-blockierenden Sockets die Anzahl der gesendeten Bytes zurückgibt.

recv(bufsize: int, flags: int = 0) bytes

Empfängt Daten vom Socket. Der Rückgabewert ist ein Bytes-Objekt, das die empfangenen Daten repräsentiert. Die maximale Datenmenge, die auf einmal empfangen werden kann, wird durch bufsize angegeben.

Das optionale Argument flags ist ein bitweises ODER von Nachrichten-Flags (MSG_PEEK, MSG_DONTWAIT), die dieselbe Bedeutung wie in CPython haben.

sendto(bytes: bytes, address: Any) int

Sendet Daten an den Socket. Der Socket sollte nicht mit einem entfernten Socket verbunden sein, da der Ziel-Socket durch address angegeben wird.

recvfrom(bufsize: int, flags: int = 0) Tuple[bytes, Tuple]

Empfängt Daten vom Socket. Der Rückgabewert ist ein Paar (bytes, address), wobei bytes ein Bytes-Objekt ist, das die empfangenen Daten repräsentiert, und address die Adresse des Sockets ist, der die Daten sendet.

Siehe die Funktion recv() für eine Erläuterung des optionalen Arguments flags.

setsockopt(level: int, optname: int, value: int | bytes) None

Setzt den Wert der angegebenen Socket-Option. Die benötigten symbolischen Konstanten sind im socket-Modul definiert (SO_* usw.). Der value kann eine ganze Zahl oder ein bytes-ähnliches Objekt sein, das einen Puffer repräsentiert.

settimeout(value: float | None) None

Setzt einen Timeout für blockierende Socket-Operationen. Das value-Argument kann eine nicht-negative Gleitkommazahl sein, die Sekunden ausdrückt, oder None. Wenn ein Wert ungleich null angegeben wird, lösen nachfolgende Socket-Operationen eine OSError-Ausnahme aus, falls der Timeout-Zeitraum abgelaufen ist, bevor die Operation abgeschlossen wurde. Wenn null angegeben wird, wird der Socket in den nicht-blockierenden Modus versetzt. Wenn None angegeben wird, wird der Socket in den blockierenden Modus versetzt.

Eine portable und generische Alternative ist die Verwendung eines select.poll-Objekts. Dies erlaubt das Warten auf mehrere Objekte gleichzeitig (und nicht nur auf Sockets, sondern auf generische stream-Objekte, die Polling unterstützen). Beispiel:

# Instead of:
s.settimeout(1.0)  # time in seconds
s.read(10)  # may timeout

# Use:
poller = select.poll()
poller.register(s, select.POLLIN)
res = poller.poll(1000)  # time in milliseconds
if not res:
    # s is still not ready for input, i.e. operation timed out

Unterschied zu CPython

CPython löst im Falle eines Timeouts eine socket.timeout-Ausnahme aus, die eine Unterklasse von OSError ist. MicroPython löst stattdessen direkt einen OSError aus. Wenn Sie except OSError: verwenden, um die Ausnahme abzufangen, funktioniert Ihr Code sowohl in MicroPython als auch in CPython.

setblocking(flag: bool) None

Setzt den blockierenden oder nicht-blockierenden Modus des Sockets: Wenn flag falsch ist, wird der Socket auf nicht-blockierend gesetzt, andernfalls auf blockierenden Modus.

Diese Methode ist eine Kurzform für bestimmte settimeout()-Aufrufe:

  • sock.setblocking(True) ist äquivalent zu sock.settimeout(None)

  • sock.setblocking(False) ist äquivalent zu sock.settimeout(0)

makefile(mode: str = 'rb', buffering: int = 0, /) Any

Gibt ein Dateiobjekt zurück, das mit dem Socket verknüpft ist. Der genaue zurückgegebene Typ hängt von den an makefile() übergebenen Argumenten ab. Die Unterstützung ist auf Binärmodi beschränkt (‚rb‘, ‚wb‘ und ‚rwb‘). CPythons Argumente encoding, errors und newline werden nicht unterstützt.

Unterschied zu CPython

Da MicroPython keine gepufferten Streams unterstützt, wird der Wert des Parameters buffering ignoriert und so behandelt, als wäre er 0 (ungepuffert).

Unterschied zu CPython

Das Schließen des von makefile() zurückgegebenen Dateiobjekts schließt AUCH den ursprünglichen Socket.

read(size: int | None = None) bytes

Liest bis zu size Bytes vom Socket. Gibt ein Bytes-Objekt zurück. Wenn size nicht angegeben wird, werden alle vom Socket verfügbaren Daten bis EOF gelesen; daher kehrt die Methode erst zurück, wenn der Socket geschlossen wird. Diese Funktion versucht, so viele Daten wie angefordert zu lesen (keine „short reads“). Bei einem nicht-blockierenden Socket ist dies jedoch möglicherweise nicht möglich, und dann werden weniger Daten zurückgegeben.

readinto(buf: bytearray | memoryview, nbytes: int | None = None) int

Liest Bytes in buf. Wenn nbytes angegeben ist, werden höchstens so viele Bytes gelesen. Andernfalls werden höchstens len(buf) Bytes gelesen. Genau wie read() folgt diese Methode der „no short reads“-Richtlinie.

Rückgabewert: Anzahl der gelesenen und in buf gespeicherten Bytes.

readline() bytes

Liest eine Zeile, die mit einem Zeilenumbruchzeichen endet.

Rückgabewert: die gelesene Zeile.

write(buf: bytes) int

Schreibt den Byte-Puffer in den Socket. Diese Funktion versucht, alle Daten in einen Socket zu schreiben (keine „short writes“). Bei einem nicht-blockierenden Socket ist dies jedoch möglicherweise nicht möglich, und der zurückgegebene Wert ist kleiner als die Länge von buf.

Rückgabewert: Anzahl der geschriebenen Bytes.

Bemerkung

MicroPython implementiert socket.error nicht. CPython hat eine veraltete socket.error-Ausnahme, die ein Alias von OSError ist; verwenden Sie in MicroPython direkt OSError, um socketbezogene Fehler abzufangen.