socket — socket-module

Deze module biedt toegang tot de BSD-socketinterface.

Verschil met CPython

Voor efficiëntie en consistentie implementeren socket-objecten in MicroPython rechtstreeks een stream (bestandsachtige) interface. In CPython moet je een socket converteren naar een bestandsachtig object met de methode makefile(). Deze methode wordt nog steeds ondersteund door MicroPython (maar doet niets), dus waar compatibiliteit met CPython van belang is, zorg dat je deze gebruikt.

Socketadresformaat(en)

Het native socketadresformaat van de socket-module is een opaak gegevenstype dat wordt geretourneerd door de functie getaddrinfo(), die gebruikt moet worden om tekstuele adressen (inclusief numerieke adressen) te resolveren:

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)

Het gebruik van getaddrinfo() is de meest efficiënte (zowel qua geheugen als verwerkingskracht) en draagbare manier om met adressen te werken.

De socket-module biedt ook een CPython-compatibele manier om adressen op te geven met tuples, zoals hieronder beschreven. Op de OpenMV Cam is de socket-module ingebouwd; numerieke adressen mogen rechtstreeks in het tuple-formaat worden opgegeven, maar domeinnamen moeten eerst worden geresolveerd met getaddrinfo().

Samengevat:

  • Gebruik altijd getaddrinfo() om hostnamen te resolveren.

  • De hieronder beschreven tuple-adressen kunnen worden gebruikt als snelkoppeling voor numerieke adressen, voor snelle hacks en interactief gebruik.

Tuple-adresformaat voor de socket-module:

  • IPv4: (ipv4_address, port), waarbij ipv4_address een string is met een numeriek IPv4-adres in puntnotatie, bijv. "8.8.8.8", en port een geheel poortnummer is in het bereik 1-65535. Domeinnamen worden niet geaccepteerd als ipv4_address; resolveer ze eerst met getaddrinfo().

  • IPv6: (ipv6_address, port, flowinfo, scopeid), waarbij ipv6_address een string is met een numeriek IPv6-adres in dubbelepuntnotatie, bijv. "2001:db8::1", en port een geheel poortnummer is in het bereik 1-65535. flowinfo moet 0 zijn. scopeid is de interface-scope-identifier voor link-local adressen. Domeinnamen worden niet geaccepteerd als ipv6_address; resolveer ze eerst met getaddrinfo().

Functies

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

Vertaal het host/port-argument naar een reeks van 5-tuples die alle benodigde argumenten bevatten voor het maken van een socket die verbonden is met die service. De argumenten af, type en proto (die dezelfde betekenis hebben als voor de functie socket) kunnen worden gebruikt om te filteren welk soort adressen worden geretourneerd. Als een parameter niet is opgegeven of nul is, kunnen alle combinaties van adressen worden geretourneerd (waarbij filtering aan de gebruikerszijde vereist is).

De resulterende lijst van 5-tuples heeft de volgende structuur:

(family, type, proto, canonname, sockaddr)

Het volgende voorbeeld laat zien hoe je verbinding maakt met een gegeven url:

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])

Aanbevolen gebruik van filterparameters:

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])

Verschil met CPython

CPython veroorzaakt een socket.gaierror-uitzondering (subklasse van OSError) in geval van een fout in deze functie. MicroPython heeft geen socket.gaierror en veroorzaakt rechtstreeks OSError. Merk op dat de foutnummers van getaddrinfo() een aparte namespace vormen en mogelijk niet overeenkomen met foutnummers uit de errno-module. Om getaddrinfo()-fouten te onderscheiden, worden ze weergegeven door negatieve getallen, terwijl standaard systeemfouten positieve getallen zijn (foutnummers zijn toegankelijk via de eigenschap e.args[0] van een uitzonderingsobject). Het gebruik van negatieve waarden is een voorlopig detail dat in de toekomst kan veranderen.

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

Converteer een binair netwerkadres bin_addr van de gegeven adresfamilie af naar een tekstuele representatie:

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

Converteer een tekstueel netwerkadres txt_addr van de gegeven adresfamilie af naar een binaire representatie:

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

Constanten

socket.AF_INET: int

IPv4-adresfamilie.

socket.AF_INET6: int

IPv6-adresfamilie.

socket.SOCK_STREAM: int

Stream (TCP) sockettype.

socket.SOCK_DGRAM: int

Datagram (UDP) sockettype.

socket.SOCK_RAW: int

Raw sockettype.

socket.IPPROTO_IP: int

Het IP-protocolniveau. Gebruikt als het level-argument voor setsockopt() samen met de IP_*-opties.

socket.IPPROTO_TCP: int

Het TCP-protocol. Je hoeft dit niet door te geven aan socket (het sockettype SOCK_STREAM selecteert het automatisch); het enige werkelijke gebruik ervan is als het level-argument voor setsockopt() samen met de TCP_*-opties.

socket.SOL_SOCKET: int

Het socketoptieniveau. Gebruikt als het level-argument voor setsockopt() samen met de SO_*-opties.

socket.SO_REUSEADDR: int

Sta de socket toe om te binden aan een adres/poort dat zich nog in de TIME_WAIT-status bevindt.

socket.SO_BROADCAST: int

Sta het verzenden van datagrammen naar een broadcast-adres toe.

socket.SO_KEEPALIVE: int

Schakel periodieke verzending van keep-alive-probes in op een verbonden socket.

socket.SO_SNDTIMEO: int

Verzendtime-out, in milliseconden, doorgegeven als het value-argument aan setsockopt().

socket.SO_RCVTIMEO: int

Ontvangsttime-out, in milliseconden, doorgegeven als het value-argument aan setsockopt().

socket.IP_ADD_MEMBERSHIP: int

Word lid van een multicastgroep. Een setsockopt()-optie op IPPROTO_IP-niveau.

socket.IP_DROP_MEMBERSHIP: int

Verlaat een multicastgroep. Een setsockopt()-optie op IPPROTO_IP-niveau.

socket.TCP_NODELAY: int

Schakel Nagle’s algoritme uit. Een setsockopt()-optie op IPPROTO_TCP-niveau.

socket.MSG_PEEK: int

Voor recv() / recvfrom(): retourneer data zonder deze uit de invoerwachtrij te verwijderen.

socket.MSG_DONTWAIT: int

Voor recv() / recvfrom(): voer de bewerking uit in niet-blokkerende modus.

Klassen

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

Maak een nieuwe socket aan met de gegeven adresfamilie, sockettype en protocolnummer. Het opgeven van proto is in de meeste gevallen niet vereist (en niet aanbevolen); het type-argument selecteert automatisch het benodigde protocol:

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

Markeer de socket als gesloten en geef alle resources vrij. Zodra dat gebeurt, mislukken alle toekomstige bewerkingen op het socket-object. De andere kant ontvangt een EOF-indicatie indien dit door het protocol wordt ondersteund.

Sockets worden automatisch gesloten wanneer ze door de garbage collector worden opgeruimd, maar het is aanbevolen om ze expliciet te close() zodra je klaar bent met werken.

bind(address: Any) None

Bind de socket aan address. De socket mag nog niet gebonden zijn.

listen(backlog: int = 2) None

Stel een server in staat om verbindingen te accepteren. Als backlog is opgegeven, moet het minstens 0 zijn (is het lager, dan wordt het op 0 gezet); het geeft het aantal niet-geaccepteerde verbindingen aan dat het systeem toestaat voordat nieuwe verbindingen worden geweigerd. Indien niet opgegeven, wordt een redelijke standaardwaarde gekozen.

accept() Tuple['socket', Tuple]

Accepteer een verbinding. De socket moet gebonden zijn aan een adres en luisteren naar verbindingen. De retourwaarde is een paar (conn, address) waarbij conn een nieuw socket-object is dat bruikbaar is om data te verzenden en ontvangen op de verbinding, en address het adres is dat gebonden is aan de socket aan de andere kant van de verbinding.

connect(address: Any) None

Maak verbinding met een externe socket op address.

send(bytes: bytes) int

Verzend data naar de socket. De socket moet verbonden zijn met een externe socket. Retourneert het aantal verzonden bytes, wat kleiner kan zijn dan de lengte van de data (“short write”).

sendall(bytes: bytes) None

Verzend alle data naar de socket. De socket moet verbonden zijn met een externe socket. In tegenstelling tot send() zal deze methode proberen alle data te verzenden, door de data stuk voor stuk achtereenvolgens te verzenden.

Het gedrag van deze methode op niet-blokkerende sockets is ongedefinieerd. Daarom wordt op MicroPython aanbevolen om in plaats daarvan de methode write() te gebruiken, die hetzelfde “geen short writes”-beleid heeft voor blokkerende sockets en het aantal verzonden bytes retourneert op niet-blokkerende sockets.

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

Ontvang data van de socket. De retourwaarde is een bytes-object dat de ontvangen data vertegenwoordigt. De maximale hoeveelheid data die in één keer kan worden ontvangen, wordt opgegeven met bufsize.

Het optionele flags-argument is een bitsgewijze OR van berichtvlaggen (MSG_PEEK, MSG_DONTWAIT), die dezelfde betekenis hebben als in CPython.

sendto(bytes: bytes, address: Any) int

Verzend data naar de socket. De socket mag niet verbonden zijn met een externe socket, aangezien de bestemmingssocket wordt opgegeven door address.

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

Ontvang data van de socket. De retourwaarde is een paar (bytes, address) waarbij bytes een bytes-object is dat de ontvangen data vertegenwoordigt en address het adres is van de socket die de data verzendt.

Zie de functie recv() voor een uitleg van het optionele flags-argument.

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

Stel de waarde van de gegeven socketoptie in. De benodigde symbolische constanten zijn gedefinieerd in de socket-module (SO_* enz.). De value kan een geheel getal of een bytes-achtig object zijn dat een buffer vertegenwoordigt.

settimeout(value: float | None) None

Stel een time-out in voor blokkerende socketbewerkingen. Het value-argument kan een niet-negatief drijvendekommagetal zijn dat seconden uitdrukt, of None. Als een waarde ongelijk aan nul wordt opgegeven, zullen volgende socketbewerkingen een OSError-uitzondering veroorzaken als de time-outperiode is verstreken voordat de bewerking is voltooid. Als nul wordt opgegeven, wordt de socket in niet-blokkerende modus geplaatst. Als None wordt opgegeven, wordt de socket in blokkerende modus geplaatst.

Een draagbaar en generiek alternatief is het gebruik van een select.poll-object. Hiermee kun je op meerdere objecten tegelijk wachten (en niet alleen op sockets, maar op generieke stream-objecten die polling ondersteunen). Voorbeeld:

# 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

Verschil met CPython

CPython veroorzaakt een socket.timeout-uitzondering in geval van een time-out, wat een subklasse van OSError is. MicroPython veroorzaakt in plaats daarvan rechtstreeks een OSError. Als je except OSError: gebruikt om de uitzondering op te vangen, werkt je code zowel in MicroPython als CPython.

setblocking(flag: bool) None

Stel de blokkerende of niet-blokkerende modus van de socket in: als flag onwaar is, wordt de socket op niet-blokkerend gezet, anders op blokkerende modus.

Deze methode is een afkorting voor bepaalde settimeout()-aanroepen:

  • sock.setblocking(True) is equivalent aan sock.settimeout(None)

  • sock.setblocking(False) is equivalent aan sock.settimeout(0)

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

Retourneer een bestandsobject dat aan de socket is gekoppeld. Het exacte geretourneerde type hangt af van de argumenten die aan makefile() zijn gegeven. De ondersteuning is beperkt tot alleen binaire modi (‘rb’, ‘wb’ en ‘rwb’). De CPython-argumenten encoding, errors en newline worden niet ondersteund.

Verschil met CPython

Aangezien MicroPython geen gebufferde streams ondersteunt, wordt de waarde van de buffering-parameter genegeerd en behandeld alsof deze 0 (ongebufferd) was.

Verschil met CPython

Het sluiten van het bestandsobject dat door makefile() wordt geretourneerd, ZAL ook de oorspronkelijke socket sluiten.

read(size: int | None = None) bytes

Lees maximaal size bytes van de socket. Retourneer een bytes-object. Als size niet is opgegeven, leest het alle beschikbare data van de socket tot EOF; als zodanig keert de methode pas terug wanneer de socket is gesloten. Deze functie probeert zoveel data te lezen als gevraagd (geen “short reads”). Dit is echter mogelijk niet haalbaar bij een niet-blokkerende socket, en dan wordt er minder data geretourneerd.

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

Lees bytes in buf. Als nbytes is opgegeven, lees dan maximaal dat aantal bytes. Anders lees je maximaal len(buf) bytes. Net als read() volgt deze methode het “geen short reads”-beleid.

Retourwaarde: het aantal bytes dat is gelezen en opgeslagen in buf.

readline() bytes

Lees een regel, eindigend op een newline-teken.

Retourwaarde: de gelezen regel.

write(buf: bytes) int

Schrijf de buffer van bytes naar de socket. Deze functie zal proberen alle data naar een socket te schrijven (geen “short writes”). Dit is echter mogelijk niet haalbaar bij een niet-blokkerende socket, en de geretourneerde waarde zal kleiner zijn dan de lengte van buf.

Retourwaarde: het aantal geschreven bytes.

Notitie

MicroPython implementeert socket.error niet. CPython heeft een verouderde socket.error-uitzondering die een alias is van OSError; gebruik in MicroPython rechtstreeks OSError om socketgerelateerde fouten op te vangen.