9.10. TCP – luotettava tavuvirta¶
TCP, Transmission Control Protocol, on toinen IP:n päällä toimiva kuljetuskerroksen palvelu. Siinä missä UDP:tä voi parhaiten kuvata ilmaisulla ”lähetä paketti ja toivo parasta”, TCP on ”avaa yhteys kahden päätepisteen välille ja käsittele sitä kaksisuuntaisena tavuputkena, jonka vastapuoli varmasti saa, oikeassa järjestyksessä ja täsmälleen kerran”. Suurin osa internetliikenteestä käyttää sitä, ja niin tekee myös suurin osa siitä, mitä kamera verkossa tekee.
9.10.1. Mitä TCP lisää IP:hen¶
TCP tekee paljon enemmän kuin UDP. Se lisää:
Yhteyden. Ennen kuin mitään dataa kulkee, kaksi päätepistettä vaihtavat lyhyen kättelyn sopiakseen, että ne keskustelevat keskenään. Yhteydellä on tila – ”avoin”, ”puoliksi suljettu”, ”suljettu” – jota molemmat osapuolet seuraavat.
Luotettavan toimituksen. Vastaanottaja kuittaa jokaisen tavun, jonka lähettäjä syöttää. Kaikki, mitä ei kuitata aikakatkaisun kuluessa, lähetetään uudelleen. Sovellus ei koskaan näe kadonnutta tavua; se näkee viiveen, kun protokolla lähettää datan uudelleen.
Järjestyksenmukaisen toimituksen. Tavut saapuvat samassa järjestyksessä kuin ne lähetettiin. Vaikka paketit saapuisivat vastaanottajalle väärässä järjestyksessä, TCP järjestää ne uudelleen ennen kuin sovellus lukee ne.
Vuonohjauksen. Jos vastaanottaja on hidas, lähettäjää käsketään hidastamaan; yhteys mukautuu heikomman pään nopeuteen.
Ruuhkanhallinnan. Jos välissä oleva verkko alkaa pudottaa paketteja, lähettäjä perääntyy, kunnes tilanne palautuu. Tämä estää yhtä yhteyttä kaatamasta tukkeutunutta linkkiä.
Kaikki tämä on automaattista. Sovelluksen käyttämä Python-API on yksinkertaisesti send(bytes) ja recv(n); TCP hoitaa kaiken muun taustalla.
9.10.2. Kättely¶
TCP-yhteys avautuu kolmivaiheisella vaihdolla ennen kuin mitään dataa päästetään läpi:
Kolmivaiheinen kättely. Kun molemmat osapuolet ovat kuitanneet, yhteys on avoin ja data voi kulkea.¶
Client lähettää SYN- (synchronise) paketin pyytääkseen avaamista. Server vastaa SYN-ACK-paketilla (synchronise + acknowledge) ja hyväksyy. Client lähettää lopullisen ACK-paketin vahvistaakseen. Tämän edestakaisen matkan jälkeen molemmat osapuolet ovat yhtä mieltä siitä, että yhteys on avoin, ja ovat synkronoineet laskurinsa seuratakseen, mitkä tavut on lähetetty ja vastaanotettu.
Kättely maksaa yhden edestakaisen matkan verran viivettä ennen kuin ensimmäinen hyödyllinen tavu kulkee läpi. Paikallisverkoissa se on millisekunti; mantereiden välisissä yhteyksissä se on noin 100 ms. Tämä on TCP:n päähinta ja syy siihen, miksi lyhyet kertaluonteiset viestit kannattaa joskus lähettää mieluummin UDP:llä.
9.10.2.1. Sulkemiskättely¶
Myös TCP-yhteydet suljetaan vaihdolla (FIN kummaltakin osapuolelta). Kumpi tahansa pää voi sulkea oman puolikkaansa yhteydestä itsenäisesti; puoliksi suljettu tila, jossa toinen osapuoli on lopettanut lähettämisen mutta toinen vielä keskustelee, on sallittu, joskin harvinainen. Sovellus yleensä vain kutsuu close() ja antaa protokollan hoitaa sulkemissekvenssin.
9.10.3. Mitä TCP ei takaa¶
Muutama asia, joiden TCP:n joskus oletetaan tekevän mutta joita se ei tee:
Viestirajoja. Sovellus lähettää tavuvirran, ei viestivirtaa. Kaksi
send(b"hello")-kutsua saattavat saapua yhtenärecv()-kutsunab"hellohello", tai kahtena vaihtelevankokoisenarecv()-kutsuna. Jos sovellus haluaa viestien kehystyksen, sen on lisättävä kehystys itse (rivinvaihto, pituusetuliite tai jokin muu). Esimerkiksi JSON-dokumenttien lähettäminen TCP:n yli edellyttää, että jokainen dokumentti erotetaan rivinvaihdolla tai jollakin muulla merkillä.Salausta. TCP kuljettaa sovelluksen sille antamat tavut, selkokielisinä, koko matkan. Jos sisällön on oltava luottamuksellista, sovelluksen on käärittävä yhteys TLS:ään (katso Salatut soketit ja TLS).
Todennusta. TCP varmistaa, että tavut saapuivat ehjinä. Se ei kerro mitään siitä, kuka ne lähetti. Todennus on niin ikään ylemmän kerroksen asia.
Elossaoloa hiljaisella yhteydellä. Jos kumpikaan osapuoli ei lähetä dataa pitkään aikaan, yhteys on teknisesti yhä avoin mutta ei voi havaita, että toinen pää on kaatunut tai kadonnut. Keepalive-luotaukset voidaan ottaa käyttöön socketissa tämän korjaamiseksi, kun sillä on merkitystä.
9.10.4. Milloin käyttää TCP:tä¶
TCP on oikea vastaus lähes mihin tahansa keskusteluun, joka sopii muotoon ”client avaa yhteyden serveriin, ne vaihtavat joitakin tavuja, yhteys sulkeutuu valmistuttuaan”. HTTP- ja HTTPS-pyynnöt, SSH-istunnot, tietokantakyselyt, tiedostonsiirrot, kuvien lataukset – kaikki TCP:n yli.
Turvaudu UDP:hen vain silloin, kun keskustelu ei sovi tuohon muotoon: itsenäiset, itsessään täydelliset viestit, joissa häviö on hyväksyttävää, multicast-liikenne, ajan synkronointi, nimihaut tai äärimmäisen viiveherkät tapaukset, joissa kättelyn hinta on liian suuri.
Kun portit, UDP ja TCP ovat kaikki esillä, kuljetuskerroksen tarina on valmis. Molemmat paljastava Python-API on seuraavalla sivulla: Socket-objektit.