TCP

**Pārraides vadības protokols** jeb **protokols ''TCP*** () ir viens no galvenajiem interneta protokoliem. *TCP* ļauj tīkla datoru programmām izveidot savienojumus no vienas uz otru, caur kurām var pārsūtīt datus. Atšķirībā no *UDP*, šis protokols nodrošina drošu un secīgu datu pārraidi. *TCP* arī atšķir dažādu programmu savienojuma datus (lietojot portu numurus).
*TCP* ir internetā plašāk lietotais [[transporta slānis|transporta slāņa]] protokols. Programmas *TCP* piegādā baitu plūsmas, ko sadala atbilstoša izmēra segmentos (kuru izmēru parasti nosaka kanāla slāņa *MTU* (*maximum transmission unit*)). Iegūtās [[pakete (informācijas tehnoloģijās)|paketes]] *TCP* tālāk piegādā IP nosūtīšanai caur tīklu. *TCP* pārbauda, vai paketes nav pazaudētas katrai paketei pieliekot sākotnējo numuru, kuru arī lieto lai pārliecinātos, ka dati ir piegādāti sākotnējā secībā. Par sekmīgi saņemtajām paketēm, TCP sūta atpakaļ apstiprinājumus. Ja sūtītājs laikus (kamēr nav iestājusies [[noildze]]) nesaņem apstiprinājumu, paketi uzskata par pazaudētu un nosūta vēlreiz. *TCP* pārbauda vai paketes dati nav bojāti, lietojot kontrolsummu.

*TCP* nav optimizēts lietošanai [[bezvadu]] tīklos. Pieņem, ka visi pakešu zudumi rodas nepietiekamas datu kanāla caurlaidības dēļ. Bezvadu tīklos pakešu zudumi rodas lielākoties citu iemeslu dēļ. Tas samazina *TCP* ātrumu šādos apstākļos, jo pēc katras pazaudētās paketes *TCP* samazina sūtīšanas ātrumu.

Lai arī *TCP* ir internetā visplašāk lietotais transporta slāņa protokols, ir daži pielietojumi, kur tas nav piemērots (tur lieto *UDP*):
* *TCP* nodrošina secīgu datu pārraidi, ja daļa datu pazūd, tos pārsūta vēlreiz un tas rada aizķeršanos. Dažiem pielietojumiem (spēlēm, *VoIP*) šāda aizķeršanās ir nevēlamāka kā datu zudumi.
* *TCP* ir samērā sarežģīts protokols, lai atvērtu savienojumu vien vajag 3 paketes (no kurām neviena nenes derīgos datus). Vēl, *TCP* darbināšanai vajag vairāk [[brīvpiekļuves atmiņa]]s nekā *UDP* (tam nav nozīmes datoriem, bet var būt nozīme *PXE*).

== Protokola darbība ==
Atšķirībā no *UDP*, kas var sākt sūtīt datus bez jebkādas iepriekšējas sagatavošanās, *TCP* nodrošina savienojumus, kurus vispirms vajag izveidot, pirms var sākt sūtīt datus. *TCP* savienojumiem ir 3 dzīves stadijas:
* Izveidošana (savienojuma atvēršana)
* Datu pārraide (savienojums ir atvērts)
* Aizvēršana (savienojuma aizvēršana)
Savienojuma galapunkti datorā ir *soketi* (*sockets*). *TCP* tiem var būt 11 stāvokļi:
# LISTEN - šajā stāvoklī sokets gaida savienojuma pieprasījumu no ārpuses, šo lieto visi *TCP* serveri
# SYN-SENT - šeit nupat no šejienes ir nosūtīts savienojuma pieprasījums uz ārēju serveri un sokets gaida atbildi
# SYN-RECEIVED - sokets nupat ir nosūtījis *SYN* paketi un gaida saņemšanas apstiprinājumu (*ACK*) (šo lieto *TCP* serveri. Šajā stadijā nonāk LISTEN savienojums pēc savienojuma pieprasījuma saņemšanas un apstiprinājuma nosūtīšanas)
# ESTABLISHED - caur šo soketu ir atvērts strādājošs savienojums, caur kuru var pārsūtīt datus
# FIN-WAIT1 - savienojuma aiztaisīšanas stadija, no šejienes ir nosūtīts savienojuma aiztaisīšanas pieprasījums uz otru galu un šis sokets gaida atbildi
# FIN-WAIT2 - savienojuma aiztaisīšanas stadija, saņēmis savienojuma aiztaisīšanas pieprasījumu (no otra gala) un gaida pēdējo *ACK* 
# CLOSE-WAIT - savienojuma aiztaisīšanas stadija, otrs gals pieprasīja aiztaisīt savienojumu, šis aizsūtīja apstiprinājumu un nonāca te
# CLOSING - savienojuma aiztaisīšanas stadija, abi gali mēģināja aiztaisīt savienojumu vienlaicīgi
# LAST-ACK - savienojuma aiztaisīšanas stadija, gaida, kamēr pienāks pēdējās šim savienojumam piederošās paketes
# TIME-WAIT - savienojuma aiztaisīšanas stadija, šajā stadijā sokets nonāk pēc savienojuma aiztaisīšanas pieprasījuma nosūtīšanas uz otru galu, te sokets gaida apstiprinājumu tam pieprasījumam. Saskaņā ar rfc793, šajā stadijā sokets var būt ne ilgāk kā 4 minūtes.
# CLOSED - šajā stadijā savienojums ir aiztaisīts, te atrodas vai nu pirms savienojuma atvēršanas (vienalga, aktīvās vai pasīvās) vai arī pēc savienojuma aiztaisīšanas.

=== Savienojuma atvēršana ===
Lai klients varētu pieslēgties serverim, tur ir jābūt atvērtam [[Ports (TCP/IP)|portam]] (*passive open*). Pēc tam klients uz turieni var sūtīt savienojuma pieprasījumu. *TCP*, tāpat kā *UDP* ir klienta-servera bāzēts protokols. Visas *TCP* implementācijas spēj darboties gan kā klients, gan kā serveris. Klients atver savienojumu uz serveri. Savienojumi sastāv no diviem vienvirziena datu kanāliem.
# Klients sūta savienojuma atvēršanas pieprasījumu *SYN* (*synchronize*, *active open*) uz serveri
# Serveris atbild ar *SYN* un *ACK* (*acknowledgment* - savienojuma izveidošanas apstiprinājums)
# Klients atbild ar *ACK* un pēc tam izveidojas savienojums starp klientu un serveri.
Piemērs:
# Klients aizsūta serverim *SYN* paketi (ar aktīvu *SYN* karodziņu). Visas *SYN* paketes satur numuru (*sequence number*), tas ir 32 bitu lauks *TCP* paketes hederī, sākumam parasti paņem nejaušu skaitli. Šim piemēram pieņemam x.
# Otrs gals (serveris) saņem paketi un pieraksta tās numuru (*sequence number*), kas šajā gadījumā ir x un nosūta atpakaļ paketi ar *SYN* un *ACK* (aktīvi *SYN* un *ACK* karodziņi paketes hederī). ACK ir 32 bitu lauks paketes hederī, tas satur nākamās sagaidāmās paketes numuru, kas šajā gadījumā ir x+1, ar šo paketi vienlaikus tiek atvērts pretējā virziena savienojums, kuras vajadzībām lieto sākotnējo numuru (*sequence number*) y.
# Sākotnējais dators (klients) aizsūta *ACK* paketi, kurai *ACK* laukā ir y+1. Ar to abu virzienu savienojumi ir sasinhronizēti.

=== Datu pārraide ===
Galvenās *TCP* atšķirības no *UDP* ir:
* secīga datu pārraide,
* atkārtota pazaudēto pakešu nosūtīšana,
* ja vienas un tās pašas paketes pienāk vairākkārtīgi, tad liekos eksemplārus izmet,
* ja paketei neatbilst kontrolsumma, to arī izmet (un gaida kad atsūtīs jaunu, labāku),
* plūsmas vadība (*congestion control* un *flow control*)
Atverot savienojumu, abi datori apmainās ar numuriem (*sequence numbers*), kas var būt jebkādi skaitļi. Šis skaitlis apraksta no attiecīgā datora nosūtīto baitu skaitu, katrai nākamajai paketei tas palielinās par iepriekšējā paketē nosūtīto baitu skaitu. Paketes apstiprinājumi (*ACK*) satur nākamo sagaidāmo kārtas numuru (pēdējais saņemtais baits +1). Ja paketes pazūd, pārsūta visu kopš pēdējā veiksmīgi apstriprinātā baita. Kārtas numuri un *ACK* nodrošina dubulto pakešu identifikāciju (tām tie būs vienādi), pazaudēto pakešu atkārtotu nosūtīšanu (ja sūtītājs laicīgi nesaņem *ACK* tas uzskata, ka pakete ir pazaudēta un nosūta vēlreiz) un secīgu datu pārraidi numuri (*sequence numbers*) atbilst nosūtīto baitu skaitam, ja saņem mazāk baitu kā būtu jābūt pēc tiem numuriem ir skaidrs, ka pa vidu kaut kā trūkst.

Lai pārliecinātos, ka dati pārsūtīšanas laikā nav bojāti, lieto 16 bitu kontrolsummu.

Plūsmas vadība (*congestion control* un *flow control*). Šīm vajadzībām *TCP* lieto vairākus mehānismus, kuri regulē nosūtīšanas ātrumu. Sūtītāji tam lieto saņemtos un nesaņemtos *ACK*. Ja saņemts *ACK*, uzskata, ka dati ir aizgājuši veiksmīgi, ja nesaņem - ka pazaudēti. Par galveno datu pazaudēšanas iemeslu uzskata savienojuma nepietiekamo datu caurlaidību (tādēļ [[maršrutētājs|maršrutētāji]] ir bijuši spiesti paketes izmest).

Pārraides logs (*transmit window*) ir ienākošo datu bufera izmērs, tas ir maksimālais datu daudzums, kādu var nosūtīt sūtītājs nesaņemot *ACK*. *ACK* paketes satur datus par atlikušo pārraides loga vietu. Ja sūtītājs saņem paziņojumu, ka pieejamais pārraides loga izmērs ir 0, tas pārtrauc sūtīt un gaida. Lai novērstu situāciju, ja pakete, kas ziņoja par jaunu brīvo vietu pārraides logā, ir pazaudēta un sakari iestrēgst, sūtītājs ik pa laikam nosūta mazu paketi, kurai atbilstošais *ACK* satur pēdējo pārraides loga (*transmit window*) izmēru.

*UDP* īpatnības ir:
* nav secīga datu pārraide (ja kāda pakete pienāk vēlāk, tā netiek sakārtota pēc kārtas numuriem),
* netiek pārsūtītas pazaudētās paketes (ja kāda pakete ir pazudusi un nav saņemta, netiek sūtīts pieprasījums pārsūtīt paketi),
* ja viena un tā pati pakete pienāk divkārt, liekos eksemplārus neizmet,
* nav vajadzīga datu pārraides uzstādīšana (paketes var tikt nosūtītas bez 3 pakāpju savienojuma izveidošanas kā tas ir ar *TCP*)
Šo protokolu galvenokārt izmanto *DNS* vai arī video un audio. *UDP* paketes tiek pārsūtītas ātrāk. Skatoties video vai klausoties mūziku, ir neiespējami pamanīt, ja kāda pakete ir pazudusi vai pienākusi vēlāk.

=== Savienojuma pārtraukšana ===
Savienojuma pārtraukšanai parasti nosūta 4 paketes. Viens gals sāk savienojuma beigšanu nosūtot *FIN* paketi, kuru otrs gals apstiprina ar *ACK*. Lai slēgtu otru savienojuma pusi, vajag vēl divas tādas pašas paketes pretējā virzienā. Dažreiz pirmo *ACK* apvieno ar otro *FIN*, tad var iztikt ar 3 paketēm. Ja pazūd sakari (nevienai nosūtītajai paketei nepienāk *ACK*), tad arī savienojums tiek pārtraukts.

=== *TCP* porti ===
*TCP* protokolā, tāpat kā *UDP* protokolā ir 65535 porti. *TCP* lieto portu numurus, lai identificētu sūtošās un saņemošās programmas savienojuma galapunktos. Katram *TCP* savienojuma galam ir piesaistīts 16 bitu skaitlis - porta numurs, pēc kura identificē ienākošās paketes. Noteiktiem serveriem parasti piesaista noteiktus portu numurus (piem. http - 80, smtp - 25, ftp - 21), kurus lieto kā noklusēto vērtību.

== *TCP* segmentu struktūra ==
*TCP* sadala ienākošo datu plūsmu segmentos (paketēs), kuras tālāk ievieto IP paketēs nosūtīšanai tālāk. *TCP* segmentu veido divas daļas - hederis un dati. *TCP* hederim ir 12 lauki, no kuriem 10 ir obligāti.


* ***Sūtītāja ports*** - identificē portu, no kura segments ir ticis nosūtīts
* ***Saņēmēja ports*** - identificē portu, uz kuru segmentu sūta
* ***Paketes kārtas numurs*** - paketes numurs, tam ir divas nozīmes:
** Ja *SYN* ir aktīvs, tad tas ir sākotnējais numurs un pirmajam datu baitam atbilst šis skaitlis +1
** Ja *SYN* nav aktīvs, tad tas atbilst pirmajam datu baitam
* ***Apstiprinājuma numurs*** - ja *ACK* ir aktīvs, tad šī lauka vērtība ir sūtītāja sagaidāmais nākamais *sequence number*
* ***Datu nobīde*** - norāda *TCP* hedera izmēru 4 baitos un attiecīgi nobīdi līdz datu sākumam. Minimālais izmērs ir 5 (maksimālais - 15).
* ***Rezervēts*** - šis lauks ir rezervēts nākotnes vajadzībām un tam ir jābūt 0.
* ***Karodziņi*** - (8) 1 bita lauki:
** CWR - *(Congestion window reduced)* šo uzliek sūtītāji, lai norādītu, ka saņēmuši *ACK* ar aktīvu *ECE*
** ECE - *(ECN-echo)* norāda, ka otra gala ierīce spēj darboties ar *ECN* protokolu (*TCP* paplašinājums)
** URG - *(Urgent pointer)* norāda, ka pakete ir jānosūta steidzami
** ACK - *(Acknowledgement number)* norāda, ka lauks satur kaut kādu vērtību (pakete satur apstiprinājumu kādai no iepriekšējām paketēm)
** PSH - *(Push)* pakete *TCP* līmenī tiek pārraidīta ātrāk
** RST - *(Reset)* aiztaisa savienojumu piespiedu kārtā, šo lieto arī lai atteiktu savienojumu
** SYN - *(Synchronize)* sinhronizē - saskaņo kārtas numurus starp klientu un serveri atverot savienojumu
** FIN - *(Finalize)* no sūtītāja vairāk datu nebūs (tiek sūtīta aizverot savienojumu)
* ***Logs*** - to izmanto vēl nepārsūtītām paketēm. Tas ļauj abām pusēm sekot līdz pakešu plūsmai, lai precīzi zinātu, ka visas paketes ir saņemtas pareizi un nosūtītu apstiprinājumu pirms sūtīt jaunu paketi.
* ***Kontrolsumma*** - 16 bitu kontrolsumma lai pārbaudītu vai hederī un datos nav kļūdu. To aprēķina pēc līdzīga algoritma kā IP kontrolsummu.
* ***Steidzamais norādījums*** - norāda, ka pakete ir jāpārsūta nekavējoties, kaut arī šis logs tiek izmantots reti.
* ***Iespējas*** - izmanto, lai noskaidrotu datu apstrādes iespējas datu saņēmējam un datu sūtītājam *TCP* līmenī. Piemēram, ja *TCP* līmenis ir spējīgs apstrādāt datus, kuru izmērs nepārsniedz norādīto maksimumu, sistēma par tādiem ierobežojumiem ziņos laukā iespējas.
* ***Dati*** - tie ir pārsūtāmie dati un nav daļa no hedera.

Kontrolsummu aprēķina datiem, visam *TCP* hederim (aizvietojot kontrolsummas lauku ar nullēm) un daļai IP hedera, kas satur abas adreses, paketes garuma lauku (16bit) protokola lauku (8bit)(identificē *TCP* un ir 6) un tukšu 8 bit lauku. (pēdējie 3 pretējā secībā). IPv6 gadījumā paketes garuma lauks nāk tieši aiz adresēm un ir 32bit, pēc tam ir 24bit nulles un aiz tām ir *next header* lauks kas identificē *TCP'' un ir 8bit.

## Atsauces