Skip to main content

10.3 Komunikácia cez TCP a cez UDP

TCP spojenia

Už vieme, že v prípade protokolu TCP sa vytvára spojenie na cieľový port servera (na ktorom „počúva“ serverová aplikácia) zo zdrojového portu klienta (ktorý sa otvorí dynamicky).

Vytvorenie a evidovanie TCP spojenia

Samotné vytvorenie spojenia je však pomerne komplikovaný proces, pri ktorom sa overuje obojstranná funkčnosť prenosu údajov. Prebieha v troch fázach, ktoré sa označujú ako „three-way handshake“:

  1. Klient odošle serveru požiadavku na vytvorenie spojenia – špeciálny synchronizačný segment s príznakom SYN zo svojho dynamicky vytvoreného portu na cieľový port služby servera.
  2. Server potvrdí požiadavku klienta odoslaním špeciálneho potvrdzovacieho segmentu s príznakom ACK, ktorý má zároveň aj príznak SYN pre požiadavku na vytvorenie spätného spojenia.
  3. Klient potvrdí požiadavku servera odoslaním potvrdenia ACK.

Takto vytvorené spojenie evidujú operačné systémy oboch komunikujúcich zariadení, ale môžu ho evidovať aj smerovače na trase – a to až do chvíle ich ukončenia. V prípade smerovača MikroTik môžeme spojenia sledovať vo WinBox ponuke IP → Firewall → Connections, pokiaľ je sledovanie spojení zapnuté.

Ukončenie a prerušenie TCP spojenia

Ukončenie spojenia neprebieha tak, že sa komunikujúce strany náhle odmlčia – u klienta by zostal zablokovaný zdrojový port, čo by viedlo k postupnému vyčerpaniu všetkých portov. Ešte väčší problém by to spôsobilo na smerovači, ktorý by prevádzal preklad adresy (NAT – ním sa budeme zaoberať čoskoro).

Korektné ukončenie spojenia prebieha až v štyroch fázach (uvedené sú fázy pre ukončenie iniciované klientom):

  1. Klient odošle serveru požiadavku na ukončenie spojenia – špeciálny segment s príznakom FIN.
  2. Server prijatie požiadavky potvrdí odoslaním ACK a nebude už prijímať ďalšie údaje.
  3. Server odošle klientovi aj samostatnú požiadavku na ukončenie spojenia FIN.
  4. Klient potvrdí prijatie požiadavky odoslaním ACK a uzavrie príslušný dynamický port.

Okrem toho existuje aj náhle ukončenie spojenia pomocou príznaku RST, napríklad zásahom firewallu.

Niekedy je však spojenie ukončené neplánovane (napríklad klient Wi-Fi sa vzdiali z dosahu Wi-Fi AP) a proces ukončovania spojenia neprebehne. V takom prípade sa uplatní časový limit (timeout). Na smerovači MikroTik je dĺžka tohto limitu definovaná vo vyššie spomínanej ponuke pod tlačidlom Tracking – položka TCP Established Timeout. Štandardne je nastavená na 1 deň, čo môže byť v prípade veľkého množstva NAT klientov (obzvlášť z Wi-Fi) príliš dlhá doba a je vhodné ju znížiť.

Kontrola doručovania

Pripomeňme si, že TCP protokol je spoľahlivý. Okrem iného to znamená, že každý segment údajov má svoje poradové číslo (SEQ). Príjemca posiela odosielateľovi potvrdenie prijatia (segment s príznakom ACK a číslom segmentu, ktorý ako ďalší očakáva) a pokiaľ segmenty prišli v nesprávnom poradí, zoradí si ich. Toto samozrejme nemusí riešiť aplikácia, je to úlohou operačného systému.

Realitou sietí je, že niektoré segmenty sa cestou môžu stratiť – nemusí to byť chybou spojenia (hoci pri bezdrôtových sieťach je to vcelku bežné), ale dôvodom môže byť aj zahltenie internetového pripojenia. Pokiaľ odosielateľ pošle napríklad 10 segmentov po 1000 B, ale príjemcovi neprišli segmenty č. 3 a 4, odošle „ACK 3“, teda potvrdenie prijatia (nevie, koľko údajov malo prísť) s očakávaním segmentu od č. 3. Odosielateľ teda pošle segmenty od čísla 3 do 10 znovu.

Toto by však bolo neefektívne, preto existuje aj selektívne potvrdenie SACK, ktoré môže potvrdiť prijatie segmentov konkrétneho rozsahu. V uvedenom príklade by príjemca odoslal „ACK 3, SACK 5-10“, teda oznámil by, že očakáva segmenty od čísla 3, ale už má prijaté č. 5 až 10. Odosielateľ teda znovu pošle segmenty č. 3, 4 a môže pridať aj ďalšie (napr. 11 a 12).

Čísla segmentov v ACK i SEQ v skutočnosti nie sú poradovým číslom segmentu, ale prenášaných bajtov. A nie sú ani číslované od 0 alebo 1, ale začínajú náhodným číslom. Je to bezpečnostné opatrenie, aby nebolo možné ľahko predvídať a falšovať segmenty. Ak sa v každom segmente prenáša napr. 1452 B, tak číslo segmentu je vždy o 1452 vyššie ako číslo predchádzajúceho segmentu. Aplikácia Wireshark sa nám snaží situáciu sprehľadniť a zobrazuje aj relatívne poradové čísla.

Môže sa samozrejme stať, že odosielateľ odoslal príjemcovi niekoľko segmentov, ale tie mu neprišli vôbec, a teda nedošlo ani k potvrdeniu. V takom prípade sa uplatní časový limit – keď odosielateľ do určitého časového limitu nedostane potvrdenie, odošle segmenty znovu.

Regulácia toku údajov

Keď už poznáme mechanizmus nadviazania a ukončenia TCP spojenia, pozrieme sa na to, ako protokol TCP spravuje prenos údajov. Už v úvode tejto témy sme si vysvetlili potrebu regulácie toku údajov – ak by neexistovala, server by mohol vysokou rýchlosťou (napr. 10 Gb/s) odoslať množstvo údajov klientovi, ktorý však má len 100 Mb/s pripojenie – teda teoreticky by stíhalo „pretiecť“ len 10 % údajov. Kde by skončilo zvyšných 90 % údajov? Neexistuje (a ani nie je žiadúci) žiadny buffer na ceste (iba na koncovom zariadení), takže by boli proste zahodené. Opakované posielanie by nemalo veľký zmysel, zbytočne by sa plytvala kapacita spojenia.

Pri TCP prenosoch sú údaje rozdelené na segmenty a odosielateľ čaká na potvrdenie každého segmentu. Neznamená to nutne, že segmenty posiela po jednom a čaká na potvrdenie každého zvlášť – prenos by bol zbytočne pomalý, no nemôže ich ani odoslať všetky plnou rýchlosťou. Používa sa preto určitý kompromis – odosiela sa vždy len určité množstvo údajov, ktoré vojde do takzvaného „okna“ a ďalšie údaje sa odošlú až po potvrdení prijatia (príznak ACK). Teda veľkosť okna definuje množstvo údajov, ktoré sú „na ceste“. Veľkosť okna špecifikuje príjemca a mala by zodpovedať veľkosti jeho buffera. Spolu s potvrdením prijatia segmentu vždy posiela aj novú veľkosť okna, ktorá môže byť iná ako pôvodná. Jednoducho povedané – odosielateľ odosiela údaje len takou rýchlosťou (a v takom množstve), ako ich príjemca stíha prijímať a spracovávať.

Toto je postačujúce pre lokálne prenosy – pozrime sa na konkrétny príklad prenosu (po už nadviazanom spojení), nech maximálna veľkosť segmentu (MSS) je 1000 B a počiatočná veľkosť okna tiež 1000 B:

  1. Odosielateľ začne prenášať údaje, veľkosť okna je 1000 B, pošle jeden segment veľkosti 1000 B.
  2. Príjemca prijme segment a odošle potvrdenie ACK s novou veľkosťou okna 2000 B („skúsi“ viac).
  3. Odosielateľ prijme potvrdenie, akceptuje novú veľkosť okna a odošle teda 2 segmenty po 1000 B.
  4. Príjemca potvrdí príjem oboch segmentov a skúsi zvýšiť veľkosť okna na 3000 B.
  5. Odosielateľ teda pošle 3 segmenty po 1000 B.
  6. Príjemca ich prijme, ale má plný buffer (údaje nestíha spracovať), preto pošle ACK s veľkosťou okna 0 B.
  7. Odosielateľ to berie na vedomie (nebude znovu odosielať segmenty), ale neodošle nič nové, čaká.
  8. Príjemca už spracoval prijaté segmenty, uvoľnil sa mu buffer a môže poslať ACK s novou veľkosťou okna.

Z hľadiska teórie sa rozlišujú dva mechanizmy:
1. riadenie toku (Flow Control) – príjemca rieši svoj buffer a spracovávanie prijatých údajov cez veľkosť okna;
2. riadenie zahltenia (Congestion Control) – odosielateľ rieši nepotvrdené segmenty a podľa nich reguluje rýchlosť.

Tento príklad však nevyjadruje situáciu pri internetovom prenose, keď má odosielateľ (server) vyššiu rýchlosť internetu ako príjemca (počítač doma). Odosielateľ by stíhal prichádzajúce údaje spracovávať (máme veľmi rýchle počítače), ale údaje neprichádzajú, lebo úzkym hrdlom je internetové pripojenie. Vyššie uvedený scenár sa bude líšiť napríklad od 6. kroku: príjemcovi neprídu všetky 3 segmenty, potvrdí teda len toľko, koľko prišlo. Odosielateľ potom pošle znovu chýbajúce segmenty a zároveň aj zníži veľkosť svojho okna odosielania (čím v konečnom dôsledku reguluje rýchlosť).

UDP komunikácia

…