9.11. Socket-objektit¶
Python-rajapinta kuljetuskerrokseen on socket.socket-luokka. Socket edustaa verkkokeskustelun yhtä päätepistettä – osoitetta, porttia ja protokollaa (UDP tai TCP), jonka yli keskustelu kulkee. Laitteistonohjausluvut avasivat UART-instansseja keskustellakseen johdolla; tämä osio avaa socket-instansseja keskustellakseen verkossa. Muoto on sama; pohjalla oleva palvelu on vain paljon kyvykkäämpi.
9.11.1. Socketin luominen¶
Kolme argumenttia kuvaa socketin: minkä osoiteperheen (address family) se puhuu, minkä socket-tyypin se tarjoaa ja mitä protokollaa se käyttää. Oletukset kattavat tapaukset, joita tämän osion loppuosa käyttää:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # IPv4 TCP
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # IPv4 UDP
Kaksi vakiota, joiden välillä sovellus valitsee lähes joka tapauksessa:
AF_INET– IPv4-osoitteet (numeerinen IP plus portti). Yleisin valinta.AF_INET6on IPv6-vastine.SOCK_STREAM– TCP-yhteys, luotettava tavuvirta.SOCK_DGRAMon UDP-vastine.
Kolmas argumentti (protokolla) jätetään nollaan, mikä valitsee oikean oletuksen kahden ensimmäisen perusteella. Täydellinen konstruktori on dokumentoitu kohdassa socket — socket-moduuli.
9.11.2. Socketin osoitteet¶
Socket-osoite on monikko (host, port)
("192.168.1.50", 80)
("0.0.0.0", 8000)
Host on IP-osoite merkkijonona. Portti on 16-bittinen kokonaisluku, joka käsitellään kohdassa Portit.
Muutama erityinen host-merkkijono kannattaa tuntea:
"0.0.0.0"tarkoittaa ”jokaista IPv4-rajapintaa tällä laitteella”. Tähän osoitteeseen sidottu palvelin hyväksyy yhteyksiä mihin tahansa osoitteeseen, joka kameralla on."127.0.0.1"on localhost – siihen suuntautuva liikenne ei koskaan poistu laitteesta. Hyödyllinen testaukseen."255.255.255.255"on paikallinen yleislähetysosoite (broadcast). Siihen lähetetty UDP-datagrammi menee jokaiselle paikallissegmentin laitteelle.
Verkkotunnukset kuten "example.com" eivät ole kelvollisia host-merkkijonoja socket-osoitteessa. Ne täytyy ensin selvittää IP-osoitteeksi; Nimet ja DNS käsittelee sen tekevän getaddrinfo()-kutsun.
9.11.3. Kaksi roolia¶
Socketin elinkaari riippuu siitä, kummalla puolella keskustelua se on. Asiakassocket kutsuu connect()-metodia (tai UDP:n tapauksessa pelkkää sendto()-metodia) keskustellakseen tunnetun palvelimen kanssa. Palvelinsocket kutsuu bind()-metodia varatakseen portin, sitten joko listen()- ja accept()-metodeja (TCP:lle) tai recvfrom()-metodia (UDP:lle) vastaanottaakseen saapuvaa liikennettä.
Samaa socket-konstruktoria käytetään molemmissa tapauksissa; vain jälkikäteen kutsutut metodit eroavat. Seuraavat kolme sivua käyvät läpi käytännön mallit:
UDP-socketit – lähetä ja vastaanota datagrammeja.
TCP-socketit – TCP-asiakas ja -palvelin.
Socketit asyncion kanssa – kaikki edellä oleva, mutta
asyncio-tapahtumasilmukan sisällä.
9.11.4. Socketin sulkeminen¶
Jokainen socket pitää hallussaan pientä käyttöjärjestelmän tilaa (porttivaraus, puskurit, yhteyden TCP-tila). Kun sovellus on valmis sen kanssa, close() vapauttaa tuon tilan. Unohdettu socket on hidas vuoto, joka kertyy; silmukassa, joka avaa yhteyksiä, close-kutsun puuttuminen lopulta tyhjentää kameran käytettävissä olevien socketien varannon.
Siistein malli on with-lause:
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
Socketit toteuttavat kontekstinhallintaprotokollan, joka käsitellään Python-yleiskatsauksessa, joten with-lohko takaa, että close() kutsutaan riippumatta siitä, poistuiko lohko normaalisti vai poikkeuksen nostamalla.
9.11.5. socket-viite¶
Tämä ja seuraavat sivut käyvät rajapinnan läpi kerronnallisessa muodossa. Jokaisen metodin, jokaisen lipun ja jokaisen moduulin tarjoaman vakion täydellinen argumenttitason viite löytyy kohdasta socket — socket-moduuli. Viite on myös paikka, josta etsiä harvinaisempia toimintoja (socket-asetukset, multicast-ryhmäjäsenyys, IPv6-laajuustunnisteet), joita tämä osio ei käsittele.