Vyšlo v týdeníku Computerworld č. 5/93 v roce 1993
Vytištěno z adresy: http://www.earchiv.cz/a93/a305c110.php3

Protokol TCP - I.

Řekne-li se dnes TCP/IP, mnoho lidí si pod tím představí dvojici protokolů: TCP (Transmission Control Protocol) a IP (Internet Protocol). Z našeho dosavadního povídání o počítačových sítích však již víme, že ve skutečnosti jde o celou soustavu protokolů (anglicky: protocol suite), spojenou s vlastní soustavou názorů na to, jak by počítačové sítě měly vypadat a jak by měly fungovat - tedy to, co jsme si již dříve označili jako síťovou architekturu či síťový model. Protokol TCP je tedy jen jedním z více protokolů soustavy TCP/IP, i když protokolem velmi významným. Dnes se u něj zastavíme podrobněji.

Nejprve si ale znovu připomeňme, že protokol TCP je protokolem transportní vrstvy, a že je jedním ze dvou alternativních protokolů, které síťový model TCP/IP na úrovni této vrstvy nabízí. Připomeňme si také důvod této nabídky dvou alternativních protokolů: jednotlivé aplikace mají možnost si vybrat, zda je pro ně výhodnější používat na úrovni transportní vrstvy nespolehlivé (ale rychlejší) přenosové služby, zajišťované protokolem UDP (User Datagram Protocol), nebo naopak pomalejší, zato ale spolehlivé služby protokolu TCP. V minulém dílu našeho seriálu jsme se podrobněji zabývali protokolem UDP a naznačili jsme si, že je vlastně jen jednoduchou obálkou nad přenosovými službami síťové vrstvy, která nijak nemění jejich kvalitu (tj. nespolehlivost) ani povahu (nespojovaný charakter), a pouze je zpřístupňuje entitám aplikační vrstvy. Úkol protokolu TCP je z tohoto pohledu mnohem náročnější - k dispozici má stejné nespolehlivé služby na úrovni síťové vrstvy, ale s jejich pomocí musí sám zajišťovat služby spolehlivé.

Další významný rozdíl mezi protokoly UDP a TCP spočívá v tom, že zatímco UDP nabízí nespojované (connectionless) služby, protokol TCP nabízí své přenosové služby jako spojované (connection-oriented). Před každou výměnou dat mezi dvěma uzly tedy musí být nejprve navázáno spojení, a po skončení přenosu musí být toto spojení zase zrušeno. Výhodami i nevýhodami spojovaných a nespojovaných služeb jsme se zabývali již ve 27. dílu našeho seriálu.

Stream, neboli proud

Dalším významným rozdílem mezi přenosovými službami protokolů TCP a UDP je také jejich pohled na přenášená data. Jak jsme si již naznačili minule, protokol UDP očekává od své bezprostředně vyšší vrstvy vždy celý blok dat, který se snaží přenést opět jako celek (v rámci jediného tzv. uživatelského datagramu, viz minule), a na straně příjemce jej předává své bezprostředně vyšší vrstvě opět jako celek.

Naproti tomu protokol TCP se snaží nabízet své bezprostředně vyšší vrstvě přenos jednotlivých bytů. Očekává tedy, že entity aplikační vrstvy mu na straně odesilatele budou postupně předávat jednotlivé byty (přesněji: osmibitové oktety), a na straně příjemce si je zase budou po jednom vyzvedávat. Tím vzniká iluze proudu (anglicky: stream) jednotlivých bytů, který navíc není nijak strukturován - tj. všechny přenášené byty jsou považovány za rovnocenné. Ve skutečnosti samozřejmě nejsou jednotlivé bity přenášeny každý zvlášť. Protokol TCP na straně odesilatele postupně akumuluje jednotlivé byty do vhodné vyrovnávací paměti (bufferu), a po jejím naplnění odešle celý její obsah najednou - v tzv. segmentu, jak se nazývá blok, přenášený protokolem TCP. Analogicky na straně příjemce, kde se datový obsah segmentu ukládá do vyrovnávací paměti, a jednotlivé byty jsou entitám aplikační vrstvy poskytovány z této vyrovnávací paměti. Celý mechanismus sdružování jednotlivých bytů do bloků je plně v režii protokolu TCP, který se přenosem větších celků snaží optimalizovat využití přenosových cest. Pro vyšší vrstvu je tento mechanismus neviditelný - vyší vrstva pracuje s představou proudu jednotlivých bytů.

Existují však takové aplikace, pro které právě naznačený mechanismus není příliš vhodný. Příkladem mohou být tzv. vzdálené terminálové relace, uskutečňované prostřednictvím sítě - kdy jeden uzlový počítač vystupuje v roli terminálu jiného počítače a jednotlivé znaky, zadané z jeho klávesnice, posílá ke zpracování tomuto druhému počítači (který mu zase posílá zpět vše, co má být zobrazeno na obrazovce terminálu). Kdyby v takovéto situaci protokol TCP čekal, až vstupní znaky naplní vyrovnávací paměť na straně odesilatele a teprve pak je skutečně odeslal, uživatel by hodně dlouho mačkal klávesy bez jakékoli odezvy. Protokol TCP však i s tímto počítá, a nabízí odesilateli mechanismus (označovaný jako push), kterým si aplikace může vynutit skutečné odeslání dat i v případě, že příslušná vyrovnávací paměť není ještě naplněna.

Jak se dosahuje spolehlivost

Již ve 30. dílu seriálu jsme si naznačili, že prakticky jedinou možností, jak pomocí nespolehlivé přenosové služby zajistit spolehlivé přenosy, je umožnit příjemci rozpoznat chybně přenesený blok, a vyžádat si jeho opětovné vyslání.

Obrázek 57.1.
Obr. 57.1.: Představa potvrzování v protokolu TCP
Ukázali jsme si také, že za tímto účelem se používá více různých způsobů tzv. potvrzování (acknowledgement), viz opět 30. díl. Protokol TCP používá tzv. kladné potvrzování (positive acknowledgement), což znamená, že potvrzuje úspěšně přijatá data, a na chybně přijatá data nereaguje nijak (ty pak odesilatel znovu vyšle na základě vypršení časového limitu, ve kterém očekával jejich kladné potvrzení). Ve své základní podobě tzv. jednotlivého kladného potvrzování (stop&wait positive acknowledgement), kdy odesilatel před odesláním každého dalšího bloku čeká na kladné potvrzení naposledy vyslaného bloku, je tento mechanismus značně neefektivní. Protokol TCP proto používá kladné potvrzování ve variantě tzv. kontinuálního potvrzování (continuous acknowledgement), známého též jako tzv. metoda okénka (sliding window). Podstata této varianty spočívá v tom, že odesilatel může odeslat další blok (resp. několik dalších bloků) ještě dříve, než dostane potvrzení o přijetí bloku předchozího. O tom, kolik bloků může takto vyslat "dopředu", rozhoduje velikost pomyslného okénka (viz obr. 30.4. ve 30. dílu).

Když jsme se ve 30. dílu zabývali různými metodami potvrzování, předpokládali jsme, že potvrzovanými jednotkami jsou celé bloky dat. V případě protokolu TCP se přenášené bloky dat označují jako segmenty, a mohou mít různou délku. V případě, že některý segment není přenesen bezchybně (resp. není kladně potvrzen do vypršení časového limitu), je jeho obsah vyslán znovu, a po něm také obsah všech následujících segmentů. Jde tedy o tzv. opakování s návratem (Go-Back-N), viz opět 30. díl. Podstatné ale je, že při tomto opakovaném vysílání již jednou vyslaných dat nemusí být dodrženy původní velikosti segmentů - znovu vyslaný segment může být větší než segment, vyslaný původně. To ale činí potvrzování celých segmentů problematické. Proto jsou v protokolu TCP potvrzovanými jednotkami dat nikoli celé bloky (segmenty), ale jednotlivé byty (přesněji: oktety)!!

Konkrétní způsob implementace potvrzování v protokolu TCP využívá plně duplexního charakteru spojení na úrovni transportní vrstvy. Jak naznačuje obrázek 57.1., každý segment obsahuje kromě vlastních dat i údaj o pozici prvního bytu těchto dat v rámci celého proudu bytů (tzv. sequence number). S využitím tohoto údaje pak příjemce původní proud bytů rekonstruuje. Jednotlivá kladná potvrzení se opět vztahují k celým bytům, a jsou vkládána do segmentů, přenášených v opačném směru, než potvrzovaná data. Jde tedy o tzv. nesamostatné potvrzování (anglicky: piggybacking), viz 30. díl. Kladné potvrzení má přitom formu čísla pozice prvního bytu (v rámci proudu), který příjemce očekává jako další (tj. prvního bytu za posledním úspěšně přijatým) - jde o tzv. acknowledgement number.