9.11. Socket objektumok

A szállítási réteg Python interfésze a socket.socket osztály. Egy socket a hálózati beszélgetés egyik végpontját képviseli – egy címet, egy portot és a protokollt (UDP vagy TCP), amelyen a beszélgetés zajlik. A hardvervezérlési fejezetek UART példányokat nyitottak, hogy egy vezetéken kommunikáljanak; ez a szakasz socket példányokat nyit, hogy a hálózaton kommunikáljon. A forma ugyanaz; az alapul szolgáló szolgáltatás csak sokkal képesebb.

9.11.1. Socket létrehozása

Három argumentum írja le a socketet: melyik címcsaládot beszéli, melyik sockettípust kínálja, és melyik protokollt használja. Az alapértelmezések lefedik azokat az eseteket, amelyeket a szakasz többi része használ:

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)   # IPv4 TCP
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)    # IPv4 UDP

A két konstans, amelyek között az alkalmazás szinte minden esetben választ:

  • AF_INET – IPv4 címek (egy numerikus IP plusz egy port). A leggyakoribb választás. A AF_INET6 az IPv6 megfelelője.

  • SOCK_STREAM – egy TCP-kapcsolat, a megbízható bájtfolyam. A SOCK_DGRAM az UDP megfelelője.

A harmadik argumentum (a protokoll) nullán marad, ami az első kettő alapján választja ki a helyes alapértelmezést. A teljes konstruktort a socket — socket modul dokumentálja.

9.11.2. Címek egy socketen

Egy socketcím egy (host, port) rendezett pár:

("192.168.1.50", 80)
("0.0.0.0", 8000)

A host az IP-cím sztringként. A port a 16 bites egész szám, amelyet a Portok tárgyal.

Néhány speciális host sztringet érdemes ismerni:

  • A "0.0.0.0" azt jelenti: „ennek az eszköznek minden IPv4 interfésze”. Az erre a címre kötött szerver bármely olyan címen fogad kapcsolatokat, amellyel a kamera rendelkezik.

  • A "127.0.0.1" a localhost – az ide irányuló forgalom soha nem hagyja el az eszközt. Teszteléshez hasznos.

  • A "255.255.255.255" a helyi szórási (broadcast) cím. Az erre küldött UDP-datagram a helyi szegmens minden eszközéhez eljut.

Az olyan tartománynevek, mint az "example.com", nem érvényes host sztringek egy socketcímben. Előbb fel kell oldani őket egy IP-re; a Nevek és DNS tárgyalja az ezt elvégző getaddrinfo() hívást.

9.11.3. A két szerep

Egy socket életciklusa attól függ, hogy a beszélgetés melyik oldalán van. Egy kliens socket a connect() (vagy UDP esetén egyszerűen a sendto()) metódust hívja, hogy egy ismert szerverrel kommunikáljon. Egy szerver socket a bind() metódust hívja, hogy lefoglaljon egy portot, majd vagy a listen() és accept() (TCP esetén), vagy a recvfrom() (UDP esetén) metódusokat a beérkező forgalom fogadásához.

Mindkét esetben ugyanazt a socket konstruktort használjuk; csak az utána hívott metódusok különböznek. A következő három oldal végigvezet a gyakorlati mintákon:

9.11.4. Socket lezárása

Minden socket egy kis darab operációsrendszer-állapotot tart fenn (egy portfoglalást, puffereket, a kapcsolat TCP-állapotát). Amikor az alkalmazás végzett vele, a close() felszabadítja ezt az állapotot. Egy elfeledett socket lassú szivárgás, amely összeadódik; egy kapcsolatokat nyitó hurokban egy elmaradt close végül kimeríti a kamera elérhető socketjeinek készletét.

A legtisztább minta a with utasítás:

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect(addr)
    s.send(b"GET / HTTP/1.0\r\n\r\n")
    ...
# socket is closed automatically here, even on error

A socketek megvalósítják a Python áttekintőben tárgyalt kontextuskezelő protokollt, így a with blokk garantálja, hogy a close() meghívásra kerül, függetlenül attól, hogy a blokk normálisan vagy kivétel kiváltásával lépett-e ki.

9.11.5. A socket referencia

Ez és a következő oldalak elbeszélő formában vezetnek végig az API-n. Minden metódus, minden jelző és minden konstans teljes, argumentumszintű referenciájáért, amelyet a modul elérhetővé tesz, lásd: socket — socket modul. A referencia egyben az a hely, ahol a ritkábban használt műveleteket (socketbeállítások, multicast csoporttagság, IPv6 hatókör-azonosítók) keresheted, amelyeket ez a szakasz nem tárgyal.