9.11. Socket-objekt¶
Python-gränssnittet mot transportlagret är klassen socket.socket. En socket representerar en ändpunkt i en nätverkskonversation – en adress, en port och det protokoll (UDP eller TCP) som konversationen körs över. Kapitlen om hårdvarustyrning öppnade UART-instanser för att kommunicera på en ledning; det här avsnittet öppnar socket-instanser för att kommunicera på nätverket. Formen är densamma; den underliggande tjänsten är bara mycket mer kapabel.
9.11.1. Skapa en socket¶
Tre argument beskriver en socket: vilken adressfamilj den talar, vilken socket-typ den erbjuder och vilket protokoll den använder. Standardvärdena täcker de fall som resten av detta avsnitt använder:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # IPv4 TCP
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # IPv4 UDP
De två konstanter som applikationen väljer mellan i nästan alla fall:
AF_INET– IPv4-adresser (en numerisk IP plus en port). Det vanligaste valet.AF_INET6är IPv6-motsvarigheten.SOCK_STREAM– en TCP-anslutning, den tillförlitliga byteströmmen.SOCK_DGRAMär UDP-motsvarigheten.
Det tredje argumentet (protokollet) lämnas på noll, vilket väljer rätt standardvärde baserat på de två första. Den fullständiga konstruktorn är dokumenterad på socket — socket-modul.
9.11.2. Adresser på en socket¶
En socket-adress är en tupel av (host, port)
("192.168.1.50", 80)
("0.0.0.0", 8000)
Värddatorn är IP-adressen som en sträng. Porten är det 16-bitars heltal som beskrivs på Portar.
En handfull speciella värdsträngar är värda att känna till:
"0.0.0.0"betyder ”varje IPv4-gränssnitt på den här enheten”. En server bunden till denna adress accepterar anslutningar på vilken adress kameran än har."127.0.0.1"är localhost – trafik till den lämnar aldrig enheten. Användbart för testning."255.255.255.255"är den lokala broadcast-adressen. Ett UDP-datagram som skickas till den går till varje enhet på det lokala segmentet.
Domännamn som "example.com" är inte giltiga värdsträngar i en socket-adress. De måste först översättas till en IP; Namn och DNS täcker anropet getaddrinfo() som gör det.
9.11.3. De två rollerna¶
En sockets livscykel beror på vilken sida av konversationen den befinner sig på. En klient-socket anropar connect() (eller, för UDP, bara sendto()) för att kommunicera med en känd server. En server-socket anropar bind() för att göra anspråk på en port, och därefter antingen listen() och accept() (för TCP) eller recvfrom() (för UDP) för att ta emot inkommande trafik.
Samma socket-konstruktor används i båda fallen; det är bara metoderna som anropas efteråt som skiljer sig. De tre nästa sidorna går igenom de praktiska mönstren:
UDP-socketar – skicka och ta emot datagram.
TCP-socketar – TCP-klient och -server.
Sockets med asyncio – allt ovanstående, men inuti en
asyncio-händelseloop.
9.11.4. Stänga en socket¶
Varje socket håller en liten bit operativsystemstillstånd (en portreservation, buffertar, anslutningens TCP-tillstånd). När applikationen är klar med den frigör close() det tillståndet. En bortglömd socket är en långsam läcka som ackumuleras; i en loop som öppnar anslutningar kommer en utebliven close så småningom att tömma kamerans pool av tillgängliga sockets.
Det renaste mönstret är with-satsen:
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
Sockets implementerar protokollet för kontexthanterare som beskrivs i Python-översikten, så with-blocket garanterar att close() anropas oavsett om blocket avslutades normalt eller genom att kasta ett undantag.
9.11.5. Referensen för socket¶
Den här och de nästa sidorna går igenom API:t i berättande form. För den fullständiga argumentnivåreferensen över varje metod, varje flagga och varje konstant som modulen exponerar, se socket — socket-modul. Referensen är också platsen att leta efter de mindre vanliga operationerna (socket-alternativ, medlemskap i multicast-grupper, IPv6-scope-ID:n) som det här avsnittet inte täcker.