9.11. Obiecte socket¶
Interfața Python pentru nivelul de transport este clasa socket.socket. Un socket reprezintă un capăt al unei conversații de rețea – o adresă, un port și protocolul (UDP sau TCP) peste care se desfășoară conversația. Capitolele despre controlul hardware deschideau instanțe UART pentru a comunica pe un fir; această secțiune deschide instanțe socket pentru a comunica pe rețea. Forma este aceeași; doar că serviciul subiacent este mult mai capabil.
9.11.1. Crearea unui socket¶
Trei argumente descriu un socket: ce familie de adrese folosește, ce tip de socket oferă și ce protocol utilizează. Valorile implicite acoperă cazurile pe care le folosește restul acestei secțiuni:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # IPv4 TCP
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # IPv4 UDP
Cele două constante între care alege aplicația în aproape toate cazurile:
AF_INET– adrese IPv4 (un IP numeric plus un port). Cea mai frecventă alegere.AF_INET6este echivalentul IPv6.SOCK_STREAM– o conexiune TCP, fluxul de octeți fiabil.SOCK_DGRAMeste echivalentul UDP.
Al treilea argument (protocolul) este lăsat la zero, ceea ce alege valoarea implicită corectă în funcție de primele două. Constructorul complet este documentat în socket — modulul socket.
9.11.2. Adrese pe un socket¶
O adresă de socket este un tuplu de forma (host, port)
("192.168.1.50", 80)
("0.0.0.0", 8000)
Hostul este adresa IP sub formă de șir de caractere. Portul este întregul pe 16 biți tratat în Porturi.
Câteva șiruri speciale de host merită cunoscute:
"0.0.0.0"înseamnă „orice interfață IPv4 de pe acest dispozitiv”. Un server legat la această adresă acceptă conexiuni pe orice adresă deține camera."127.0.0.1"este localhost – traficul către el nu părăsește niciodată dispozitivul. Util pentru testare."255.255.255.255"este adresa de difuzare (broadcast) locală. O datagramă UDP trimisă către ea ajunge la fiecare dispozitiv din segmentul local.
Numele de domeniu precum "example.com" nu sunt șiruri de host valide într-o adresă de socket. Ele trebuie mai întâi rezolvate la un IP; Nume și DNS acoperă apelul getaddrinfo() care face acest lucru.
9.11.3. Cele două roluri¶
Ciclul de viață al unui socket depinde de partea conversației pe care se află. Un socket client apelează connect() (sau, pentru UDP, doar sendto()) pentru a comunica cu un server cunoscut. Un socket server apelează bind() pentru a revendica un port, apoi fie listen() și accept() (pentru TCP), fie recvfrom() (pentru UDP) pentru a primi traficul de intrare.
Același constructor socket este folosit în ambele cazuri; diferă doar metodele apelate ulterior. Următoarele trei pagini parcurg modelele practice:
Socket-uri UDP – trimiterea și primirea de datagrame.
Socket-uri TCP – client și server TCP.
Socket-uri cu asyncio – tot ce e mai sus, dar în interiorul unei bucle de evenimente
asyncio.
9.11.4. Închiderea unui socket¶
Fiecare socket deține o mică porțiune de stare a sistemului de operare (o rezervare de port, tampoane, starea TCP a conexiunii). Când aplicația a terminat cu el, close() eliberează acea stare. Un socket uitat este o scurgere lentă care se acumulează; într-o buclă care deschide conexiuni, omiterea unui close va epuiza în cele din urmă rezerva de socket-uri disponibile a camerei.
Cel mai curat model este instrucțiunea with
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
Socket-urile implementează protocolul de gestionar de context (context-manager) tratat în prezentarea generală Python, așa că blocul with garantează că close() este apelat indiferent dacă blocul s-a încheiat normal sau prin ridicarea unei excepții.
9.11.5. Referința modulului socket¶
Această pagină și următoarele parcurg API-ul în formă narativă. Pentru referința completă, la nivel de argumente, a fiecărei metode, fiecărui indicator și fiecărei constante pe care le expune modulul, consultați socket — modulul socket. Referința este de asemenea locul în care găsiți operațiile mai puțin frecvente (opțiuni de socket, apartenența la grupuri multicast, ID-urile de domeniu IPv6) pe care această secțiune nu le acoperă.