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.

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 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₧ d°φve 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φ.

Ukßzali jsme si takΘ, ₧e za tφmto ·Φelem se pou₧φvß vφce r∙zn²ch zp∙sob∙ tzv. potvrzovßnφ (acknowledgement). 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.

Kdy₧ jsme se 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). 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 posledm ·sp∞Ün∞ p°ijat²m) - jde o tzv. acknowledgement number.

 

Protokol TCP - II.

V minulΘm dφlu jsme se zaΦali zab²vat protokolem TCP. ╪ekli jsme si, ₧e svΘ bezprost°edn∞ vyÜÜφ vrstv∞ poskytuje p°enosovΘ slu₧by spolehlivΘho a spojovanΘho charakteru, i kdy₧ k jejich zajiÜt∞nφ m∙₧e sßm vyu₧φvat jen nespolehlivΘ (a nespojovanΘ) p°enosovΘ slu₧by na ·rovni sφ¥ovΘ vrstvy, poskytovanΘ protokolem IP. NaznaΦili jsme si takΘ, ₧e pot°ebnΘ spolehlivosti dosahuje protokol TCP pomocφ potvrzovßnφ a opakovanΘho vysφlßnφ chybn∞ p°enesen²ch dat. Dnes se zastavφme podrobn∞ji prßv∞ u zp∙sobu opakovßnφ p°enos∙.

P°ipome≥me si vÜak jeÜt∞ jednou to, co jsme si o konkrΘtnφm mechanismu potvrzovßnφ °ekli ji₧ minule: protokol TCP pou₧φvß tzv. kladnΘ potvrzovßnφ (positive acknowledgement), co₧ znamenß, ₧e potvrzuje pouze sprßvn∞ p°ijatß data, zatφmco na chybn∞ p°ijatß data nereaguje nijak. Odesilatel proto poznß, ₧e urΦitß data nebyla p°enesena sprßvn∞, a₧ po vyprÜenφ urΦitΘho ΦasovΘho limitu. SouΦasn∞ s tφm je ale dobrΘ si uv∞domit, ₧e takΘ kladnß potvrzenφ jsou sama p°enßÜena pomocφ stejn∞ nespolehliv²ch p°enosov²ch slu₧eb sφ¥ovΘ vrstvy, jako samotnß data. M∙₧e se proto stßt, ₧e urΦitß data jsou p°enesena bezchybn∞, ale "ztratφ" se jejich kladnΘ potvrzenφ. Odesilatel vÜak nemß mo₧nost oba tyto p°φpady rozliÜit. V₧dy musφ Φekat a₧ do vyprÜenφ ΦasovΘho limitu, zda nedostane kladnΘ potvrzenφ, a pokud ne, musφ data vyslat znovu.

Otßzkou ovÜem je, jak volit p°φsluÜn² Φasov² limit (timeout)? Bude-li p°φliÜ krßtk², m∙₧e dochßzet k situacφm, kdy data budou p°enesena bezchybn∞, ale jejich kladnΘ potvrzenφ dojde odesilateli p°φliÜ pozd∞ - a₧ po vyprÜenφ ΦasovΘho limitu, co₧ odesilatele p°inutφ znovu vyslat ·sp∞Ün∞ p°enesenß data. V opaΦnΘm p°φpad∞ - bude-li Φasov² limit p°φliÜ dlouh² - bude odesilatel zase zbyteΦn∞ dlouho Φekat, ne₧ si bude moci domyslet, ₧e se data nep°enesla sprßvn∞. V obou p°φpadech je v²sledkem neefektivnφ vyu₧itφ p°enosov²ch kapacit. ProblΘm vhodnΘ volby ΦasovΘho limitu je navφc komplikovßn skuteΦnostφ, ₧e protokol TCP m∙₧e b²t pou₧φvßn v r∙zn²ch sφtφch, ve kter²ch se doby p°enosu mohou liÜit i v n∞kolika °ßdech. Nap°φklad v rychlΘ lokßlnφ sφti by p°φsluÜn² Φasov² limit m∞l b²t v²razn∞ kratÜφ ne₧ v rozlehlΘ sφti, kterß pou₧φvß relativn∞ velmi pomalΘ pevnΘ telefonnφ okruhy. Situace je navφc jeÜt∞ komplikovan∞jÜφ u vzßjemn∞ propojen²ch sφtφ (internets, s mal²m "i"), kde jednotlivΘ Φßsti p°enosovΘ trasy (route) majφ obecn∞ r∙znΘ p°enosovΘ kapacity, a kde se navφc trasa mezi dv∞ma koncov²mi ·Φastnφky m∙₧e v pr∙b∞hu p°enosu dynamicky m∞nit (nap°. v d∙sledku zahlcenφ Φi v²padku).

Adaptivnφ chovßnφ

Zp∙sob, jak²m se protokol TCP vyrovnßvß s problΘmem sprßvnΘ volby ΦasovΘho limitu pro opakovanΘ vysφlßnφ (retransmission), lze v prvnφm p°iblφ₧enφ charakterizovat jako adaptivnφ. TCP toti₧ pr∙b∞₧n∞ monitoruje skuteΦnΘ chovßnφ p°enosovΘ sφt∞, a podle n∞j se sna₧φ p°edvφdat jejφ chovßnφ i pro nejbli₧Üφ Φasov² ·sek. Tomu pak p°izp∙sobuje i svΘ chovßnφ.

TCP neustßle m∞°φ dobu obrßtky (RTT, round trip time) jako dobu od odeslßnφ dat do p°ijetφ kladnΘho potvrzenφ o jejich ·sp∞ÜnΘm doruΦenφ. ╚asov² limit pak uzp∙sobuje pr∙m∞rnΘ dob∞ obrßtky, kterou vypoΦφtßvß jako vß₧en² pr∙m∞r (weighted average) jednotliv²ch nam∞°en²ch dob obrßtky.

NejednoznaΦnost potvrzovßnφ

V minulΘm dφlu jsme si takΘ °φkali, ₧e protokol TCP nepotvrzuje celΘ segmenty (jak se naz²vajφ jφm p°enßÜenΘ bloky dat), ale jednotlivΘ byty (p°esn∞ji: oktety) v rßmci p°enßÜenΘho proudu (stream). To mß jeden zßva₧n² d∙sledek pro v²poΦet doby odezvy. P°edstavme si situaci, kdy odesilatel nedostane do ΦasovΘho limitu kladnΘ potvrzenφ o p°ijetφ urΦitΘ Φßsti dat, a tak je vyÜle znovu ve stejn∞ velkΘm segmentu. Dostane-li pak kladnΘ potvrzenφ, nenφ z n∞j schopen rozliÜit, ke kterΘmu segmentu se toto potvrzenφ vztahuje - zda jde o potvrzenφ poprvΘ vyslan²ch dat (kterΘ se n∞kde zdr₧elo), nebo zda jde ji₧ o potvrzenφ podruhΘ vyslan²ch dat (zatφmco poprvΘ vyslanß data se p°enesla s chybou, nebo se jejich kladnΘ potvrzenφ ztratilo). Potvrzovßnφ, pou₧φvanΘ protokolem TCP, je proto v obecnΘm p°φpad∞ nejednoznaΦnΘ (ambiquous).

Z pohledu zabezpeΦenφ spolehlivΘho p°enosu tato nejednoznaΦnost nijak nevadφ, ale problΘm vznikß p°i v²poΦtu doby obrßtky: mß tato b²t vzta₧ena k okam₧iku prvnφho vyslßnφ, nebo naopak k okam₧iku poslednφho opakovanΘho vyslßnφ urΦit²ch dat? Dß se ukßzat, ₧e ob∞ varianty jsou ÜpatnΘ - v p°φpad∞ tΘ prvnφ m∙₧e vß₧en² pr∙m∞r doby obrßtky r∙st nade vÜechny meze, zatφmco ve druhΘm p°φpad∞ sice konverguje k urΦitΘ koneΦnΘ hodnot∞, ale tato je menÜφ, ne₧ by sprßvn∞ m∞la b²t (praktickΘ implementace tΘto varianty ukazujφ, ₧e je tato hodnota p°ibli₧n∞ poloviΦnφ oproti sprßvnΘ, a protokol TCP pak vysφlß vÜechna data prßv∞ dvakrßt).

Karn∙v algoritmus

S jednoduch²m a elegantnφm °eÜenφm poprvΘ p°iÜel radioamatΘr Phil Karn, kdy₧ se sna₧il implementovat TCP/IP protokoly i pro prost°edφ radioamatΘrsk²ch paketov²ch sφtφ (co₧ se mu ostatn∞ povedlo - v²sledkem je znßm² programov² balφk KA9Q, nazvan² podle volacφ znaΦky svΘho autora).

MyÜlenka, se kterou Karn p°iÜel, je velmi jednoduchß - v p°φpad∞ nejednoznaΦnΘho potvrzenφ (tj. v p°φpad∞ opakovanΘho vyslßnφ ji₧ jednou vyslan²ch dat) v∙bec nem∞°it dobu obrßtky, a tudφ₧ i neuzp∙sobovat podle nφ Φasov² limit. Jin²mi slovy: pro stanovenφ ΦasovΘho limitu vyu₧φvat pouze ty p°φpady, kdy data byla vyslßna jen jednou, a je tudφ₧ jasnΘ, jak dobu obrßtky m∞°it.

I toto °eÜenφ vÜak ve svΘ ΦistΘ podob∞ nenφ p°φliÜ pou₧itelnΘ. P°edstavme si toti₧ situaci, kdy nap°φklad vlivem zm∞ny trasy Φi v²padku Φßsti p°enosov²ch kapacit nßhle vzroste zpo₧d∞nφ p°i p°enosu. Potvrzenφ nestihne p°ijφt vΦas, a tak jsou data vyslßna znovu - v d∙sledku toho se pak ale nem∞°φ doba obrßtky, a nijak se nem∞nφ ani Φasov² limit. Bude-li nßr∙st zpo₧d∞nφ trval², v²Üe uveden² algoritmus na n∞j v∙bec nezareaguje! KonkrΘtnφ algoritmus, kter² Phil Karn navrhl, vÜak °eÜφ i tuto situaci (technikou, oznaΦovanou jako timer backoff): v okam₧iku, kdy zaΦne dochßzet k opakovanΘmu vysφlßnφ dat, p°estßvß tento algoritmus m∞°it dobu obrßtky, a nem∞nφ tudφ₧ ani vß₧en² pr∙m∞r t∞chto dob. ZaΦne ale zv∞tÜovat Φasov² limit (nap°. na dvojnßsobek po ka₧dΘm opakovanΘm vyslßnφ dat). Teprve v okam₧iku, kdy dφky v∞tÜφmu ΦasovΘmu limitu dostane kladnΘ potvrzenφ vΦas (tj. jako jednoznaΦnΘ potvrzenφ), zm∞°φ skuteΦnou dobu obrßtky, znovu zaΦne vypoΦφtßvat vß₧en² pr∙m∞r dob obrßtky, a tomuto pr∙m∞ru pak uzp∙sobφ Φasov² limit.

 

Protokol TCP - III.

V minulΘm dφlu jsme se zab²vali tφm, jak se protokol TCP vyrovnßvß s r∙znou propustnostφ p°enosov²ch cest, a jak dokß₧e dynamicky p°izp∙sobovat sv∙j mechanismus potvrzovßnφ okam₧it²m zm∞nßm tzv. doby obrßtky. K tomu, aby protokol TCP dokßzal co nejefektivn∞ji vyu₧φt existujφcφ p°enosovΘ kapacity, to ale jeÜt∞ nestaΦφ.

DalÜφm d∙le₧it²m p°edpokladem pro zajiÜt∞nφ spolehlivΘho, ale souΦasn∞ s tφm i dostateΦn∞ efektivnφho p°enosu, je vhodnΘ °φzenφ toku (flow control). Protokol TCP musφ zajistit, aby odesilatel neposφlal data rychleji, ne₧ je p°φjemce schopen je p°ijφmat (resp. uklßdat do sv²ch vyrovnßvacφch pam∞tφ). Pokud by toti₧ odesilatel p°φjemce "zahltil", tento by musel p°ijφmanß data zahazovat, a ta by musela b²t poslΘze vysφlßna znovu. Odesilatel se tedy nutn∞ musφ °φdit kapacitnφmi mo₧nostmi p°φjemce. KonkrΘtnφ zp∙sob, jak²m se v protokolu TCP dosahuje pot°ebnΘho °φzenφ toku, bezprost°edn∞ souvisφ s mechanismem potvrzovßnφ.

OkΘnko prom∞nlivΘ velikosti

Kdy₧ jsme si dφlu popisovali mechanismus potvrzovßnφ v protokolu TCP, °ekli jsme si, ₧e jde o tzv. kladnΘ potvrzovßnφ (tj. takovΘ, kdy p°φjemce kladn∞ potvrzuje sprßvn∞ p°ijatß data, a na chybn∞ p°enesenß data nereaguje). Protokol TCP ovÜem pou₧φvß tento zp∙sob potvrzovßnφ v tzv. kontinußlnφ variant∞, kdy umo₧≥uje, aby odesilatel vysφlal data "dop°edu", tedy jeÜt∞ d°φve, ne₧ dostane potvrzenφ o ·sp∞ÜnΘm p°ijetφ d°φve vyslan²ch dat. Existuje zde samoz°ejm∞ urΦitΘ omezenφ na objem dat, kterΘ se takto mohou vyslat "dop°edu", a je dßno velikostφ posuvnΘho datovΘho okΘnka (sliding window). Okam₧itß velikost a poloha tohoto okΘnka urΦuje odesilateli, kolik dat jeÜt∞ m∙₧e vyslat, ani₧ by musel Φekat na potvrzenφ od prot∞jÜφ strany.

P°φjemce mß samoz°ejm∞ mo₧nost °φdit tok dat tφm, ₧e doΦasn∞ pozdr₧φ kladnΘ potvrzenφ ·sp∞Ün∞ p°ijat²ch dat. Tφm toti₧ zabrßnφ odesilateli, aby si posunul svΘ datovΘ okΘnko, a nedovolφ mu tudφ₧ vyslat dalÜφ data za okam₧it²m koncem okΘnka. Tato metoda mß ale nep°φjemn² vedlejÜφ efekt v tom, ₧e kdy₧ p°φjemce pozdr₧φ kladnΘ potvrzenφ a odesilatel jej nedostane do p°φsluÜnΘho ΦasovΘho limitu (viz minule), bude to interpretovat tak, ₧e tato data nebyla ·sp∞Ün∞ p°enesena. V d∙sledku toho pak odesilatel znovu odeÜle ji₧ jednou odeslanß a ·sp∞Ün∞ p°ijatß data. Tato sice ji₧ nemohou p°φjemce "zahltit" (ten je m∙₧e jednoduÜe ignorovat), ale jejich p°enos zbyteΦn∞ spot°ebovßvß Φßst existujφcφ p°enosovΘ kapacity.

Protokol TCP proto pou₧φvß jin² zp∙sob °φzenφ toku, kter²m je zm∞na velikosti posuvnΘho okΘnka. P°φjemce reaguje na ka₧d² ·sp∞Ün² p°enos dat tφm, ₧e poÜle p°φsluÜnΘ kladnΘ potvrzenφ, a odesilatel si na zßklad∞ tohoto potvrzenφ p°φsluÜn²m zp∙sobem posune svΘ datovΘ okΘnko. SouΦasn∞ s tφmto potvrzenφm ale p°φjemce zaÜle odesilateli jeÜt∞ i dalÜφ ·daj, podle kterΘho si odesilatel nov∞ nastavφ Üφ°ku svΘho datovΘho okΘnka.

P°φjemce tento ·daj samoz°ejm∞ volφ podle sv²ch mo₧nostφ tak, aby v₧dy byl schopen p°ijmout to, co mu odesilatel poÜle. P°φjemce dokonce m∙₧e odesilateli zmenÜit jeho datovΘ okΘnko a₧ na nulovou velikost, a tφm vlastn∞ zcela zastavit vysφlßnφ jak²chkoli dat. P°φjemce by ale p°i stanovovßnφ novΘ velikosti okΘnka m∞l v₧dy postupovat korektn∞ - jeliko₧ nem∙₧e p°esn∞ urΦit okam₧ik, kdy odesilatel dostane ·daj o novΘ velikosti okΘnka, nem∞l by se jeho prav² okraj nikdy posouvat zp∞t.

Nejde jen o koncovΘ ·Φastnφky

Pot°eba °φdit tok dat se vÜak net²kß jen obou koncov²ch ·Φastnφk∙ p°enosu. Je toti₧ nutnΘ si uv∞domit, ₧e na cest∞ od odesilatele k p°φjemci mohou data prochßzet i p°es n∞kolik p°epojovacφch uzl∙ (gateways), kterΘ takΘ majφ jen koneΦnou propustnost. Odesilatel tedy musφ dßvat pozor i na to, aby nezp∙sobil zahlcenφ (tzv. zßcpu, angl. congestion) t∞chto meziΦlßnk∙.

Protokol TCP vÜak neobsahuje ₧ßdn² explicitnφ mechanismus, kter² by m∞l za ·kol ochranu t∞chto meziΦlßnk∙ p°ed zahlcenφm (congestion control). Sna₧φ se ale chovat tak, aby k zahlcovßnφ mezilehl²ch p°epojovacφch uzl∙ nedochßzelo.

Pro sprßvnΘ pochopenφ podstaty celΘho problΘmu je vhodnΘ si uv∞domit, jak se takovΘ zahlcenφ mezilehlΘho uzlu projevφ koncov²m ·Φastnφk∙m komunikace. Jakmile p°epojovacφ uzel (gateway) nestaΦφ p°epojovat p°enßÜenß data v reßlnΘm Φase, tato se hromadφ v jeho vstupnφch frontßch, kde Φekajφ na svΘ dalÜφ zpracovßnφ. Tento stav se koncov²m ·Φastnφk∙m projevuje r∙stem doby obrßtky. Jakmile ale zatφ₧enφ p°epojovacφho uzlu stoupne natolik, ₧e jeho vstupnφ fronty ji₧ svou kapacitou nestaΦφ, musφ p°epojovacφ uzel nov∞ p°ijφmanΘ bloky dat zahazovat, proto₧e je nemß kam ulo₧it. Mechanismy potvrzovßnφ, kterΘ se sna₧φ zajistit spolehliv² p°enos, reagujφ na ob∞ tyto situace opakovan²m vysφlßnφm ji₧ jednou vyslan²ch dat, tedy vlastn∞ dalÜφm zv²Üenφm provozu v sφti, co₧ dßle zhorÜuje p°etφ₧enφ p°epojovacφch uzl∙, a m∙₧e vΘst a₧ k ·plnΘmu zhroucenφ sφt∞ v d∙sledku zahlcenφ (congestion collapse).

Jednou z mo₧nostφ, jak p°edchßzet zahlcovßnφ p°epojovacφch uzl∙, je dßt jim mo₧nost upozornit odesilatele na hrozφcφ nebezpeΦφ. To vÜak op∞t stojφ urΦitou Φßst p°enosovΘ kapacity. DalÜφ, mΘn∞ nßkladnou mo₧nostφ, je vhodnß disciplφna samotn²ch odesilatel∙.

Protokol TCP se sna₧φ p°edchßzet zahlcovßnφ p°epojovacφch uzl∙ tφm, ₧e odesilatel si sßm zmenÜuje Üφ°ku svΘho datovΘho okΘnka v situaci, kdy p°edpoklßdß hrozφcφ zahlcenφ p°epojovacφch uzl∙. Ka₧dou ztrßtu datovΘho segmentu (tj. ka₧d² p°φpad, kdy nedostane kladnΘ potvrzenφ do p°φsluÜnΘho ΦasovΘho limitu), interpretuje odesilatel jako d∙sledek zahlcenφ n∞kterΘho z p°epojovacφch uzl∙ na cest∞ k p°φjemci, a reaguje na to tφm, ₧e si sßm z·₧φ svΘ datovΘ okΘnko na polovinu (souΦasn∞ s tφm prodlu₧uje na dvojnßsobek i Φasov² limit, do kterΘho oΦekßvß kladnΘ potvrzenφ, viz minule). P°i opakovan²ch ztrßtßch p°enßÜen²ch segment∙ tak velikost okΘnka exponencißln∞ klesß, Φφm₧ se odesilatel sna₧φ maximßln∞ snφ₧it objem provozu v sφti, a poskytnout tak p°epojovacφm uzl∙m pot°ebn² Φas na zotavenφ. Tato technika je oznaΦovßna jako Multiplicative Decrease Congestion Avoidance.

Otßzkou ovÜem je, jak mß protokol TCP reagovat na konec stavu zahlcenφ. Kdyby zaΦal op∞t exponencißln∞ zv∞tÜovat velikost svΘho datovΘho okΘnka, vedlo by to na prudkou oscilaci celΘ p°enosovΘ sφt∞ mezi stavem s minimßlnφm objemem p°enos∙ a stavem zahlcenφ. Proto musφ protokol TCP postupovat "umφrn∞n∞ji", a svΘ datovΘ okΘnko zv∞tÜovat pomaleji (zp∙sobem, kter² je oznaΦovßn jako slow-start recovery, doslova: zotavenφ s pomal²m startem). Za ka₧d² ·sp∞Ün∞ p°enesen² segment si odesilatel zv∞tÜφ svΘ datovΘ okΘnko jen o velikost tohoto segmentu. Jakmile vÜak dosßhne poloviny tΘ velikosti okΘnka, kterou mu nabφzφ p°φjemce (viz v²Üe), postupuje jeÜt∞ pomaleji, a velikost okΘnka zv∞tÜuje v₧dy a₧ potΘ, co dostane kladnΘ potvrzenφ o ·sp∞ÜnΘm p°enosu vÜech segment∙ v rßmci celΘho okΘnka. Maximßlnφ velikostφ okΘnka je pak samoz°ejm∞ ta, kterou mu signalizuje p°φjemce.

Kombinacφ vÜech v²Üe uveden²ch mechanism∙ pro °φzenφ toku, spolu s adaptivnφm zp∙sobem potvrzovßnφ (o kterΘm jsme si povφdali minule) dosahuje protokol TCP velmi efektivnφho vyu₧itφ existujφcφch p°enosov²ch kapacit. PraktickΘ testy ukßzaly, ₧e oproti prvnφm verzφm protokolu TCP, kterΘ uvedenΘ mechanismy jeÜt∞ nepou₧φvaly, dosahujφ nov∞jÜφ verze TCP dvakrßt a₧ desetkrßt v∞tÜφho p°enosovΘho v²konu. To je jist∞ jeden z hlavnφch d∙vod∙ dneÜnφ velkΘ popularity protokolu TCP.

 

Protokol TCP - IV.

Po p°edchßzejφcφch t°ech dφlech, ve kter²ch jsme se zab²vali celkovou filosofiφ protokolu TCP a jeho p°φstupem k °eÜenφ r∙zn²ch problΘm∙, ji₧ m∙₧eme b²t pon∞kud konkrΘtn∞jÜφ. M∙₧eme si ukßzat p°esn² formßt datov²ch blok∙, se kter²m protokol TCP pracuje.

Nejprve si ale p°ipome≥me, ₧e bloky dat, p°enßÜenΘ protokolem TCP jako celek, se oznaΦujφ jako segmenty (segments), zatφmco v p°φpad∞ alternativnφho protokolu UDP jde o tzv. u₧ivatelskΘ datagramy (user datagrams). V obou p°φpadech je p°enßÜen² datov² blok tvo°en dv∞ma hlavnφmi Φßstmi: hlaviΦkou (header) a vlastnφmi daty. Zatφmco ale v p°φpad∞ protokolu UDP staΦφ, kdy₧ hlaviΦka krom∞ zabezpeΦovacφho ·daje a p°φznaku dΘlky obsahuje ji₧ jen ·daj o portu koncovΘho p°φjemce a odesilatele, hlaviΦka TCP segmentu musφ b²t obsa₧n∞jÜφ - jak je ostatn∞ mo₧nΘ oΦekßvat v p°φpad∞ v²razn∞ slo₧it∞jÜφho p°enosovΘho protokolu.

╚φm je urΦeno spojenφ

SpojovanΘ (connection-oriented) protokoly, mezi kterΘ pat°φ i protokol TCP, musφ v₧dy n∞jak²m zp∙sobem identifikovat konkrΘtnφ spojenφ, po kterΘm jsou urΦitß data p°enßÜena. SpojovanΘ protokoly sφ¥ovΘ vrstvy majφ blφ₧e k p°edstav∞ spojenφ jako kanßlu, kter² n∞kudy vede, a tak jej obvykle oznaΦujφ jednoznaΦn²m identifikßtorem (nap°. Φφslem). Tento identifikßtor pak pou₧φvajφ jak pro zanesenφ p°φsluÜnΘ cesty do sm∞rovacφch tabulek mezilehl²ch uzl∙, p°es kterΘ spojenφ prochßzφ, tak i ve vlastnφch datov²ch paketech pro urΦenφ cesty, kterou majφ b²t p°enßÜeny (mφsto adresy p°φjemce). SpojovanΘ protokoly na ·rovni transportnφ vrstvy (co₧ je p°φpad protokolu TCP) vÜak ji₧ "nevidφ" ₧ßdnΘ mezilehlΘ uzly, nepot°ebujφ brßt je v ·vahu, a je pro n∞ p°irozen∞jÜφ identifikovat spojenφ dvojicφ: .

Co je ale koncov²m a poΦßteΦnφm bodem spojenφ v p°φpad∞ protokolu TCP? IP adresa p°φjemce a odesilatele nestaΦφ, nebo¥ ta jednoznaΦn∞ identifikuje pouze uzlov² poΦφtaΦ, a nikoli ji₧ konkrΘtnφ entitu aplikaΦnφ vrstvy v rßmci danΘho uzlu. Obdobn∞ nenφ samo o sob∞ dostateΦnΘ ani Φφslo portu , kterΘ zase identifikuje aplikaΦnφ entitu v rßmci danΘho poΦφtaΦe. PoΦßteΦnφ (a stejn∞ tak i koncov²) bod spojenφ m∙₧e b²t urΦen a₧ dvojicφ <IP adresa, Φφslo portu>.

Jak ovÜem vypl²vß, v TCP segmentu jsou vyjßd°eny pouze Φφsla port∙ odesilatele a p°φjemce. Pot°ebnΘ IP adresy jsou pak, obdobn∞ jako v p°φpad∞ protokolu UDP, souΦßstφ tzv. pseudohlaviΦky, kterß je shodnß s pseudohlaviΦkou protokolu UDP (samoz°ejm∞ a₧ na obsah pole PROTO, kterΘ identifikuje transportnφ protokol, a pro TCP mß hodnotu 6). Stejn² jako u protokolu UDP je i v²znam pseudohlaviΦky a zp∙sob jejφho vyu₧itφ - je zahrnuta do v²poΦtu kontrolnφho souΦtu (polo₧ka CHECKSUM v TCP segmentu), ale ve skuteΦnosti p°enßÜena nenφ. Obsah jednotliv²ch polo₧ek (p°edevÜφm pak ob∞ IP adresy) dostßvß transportnφ vrstva na stran∞ p°φjemce od vrstvy sφ¥ovΘ.

KladnΘ potvrzovßnφ

Z p°edchozφch dφl∙ ji₧ takΘ vφme, ₧e protokol TCP pou₧φvß kladnΘ potvrzovßnφ - nikoli ovÜem cel²ch blok∙ (segment∙), ale jednotliv²ch byt∙ (osmibitov²ch oktet∙). P°φjemce i odesilatel se dφvajφ na p°enßÜenß data jako na lineßrnφ posloupnost byt∙, a v ka₧dΘm segmentu se vlastn∞ p°enßÜφ Φßst tΘto lineßrnφ posloupnosti. Kterß Φßst to je, udßvß polo₧ka SEQUENCE NUMBER v hlaviΦce segmentu (vyjad°ujφcφ pozici prvnφho p°enßÜenΘho bytu v tΘto posloupnosti). KladnΘ potvrzenφ, kterΘ p°φjemce vracφ odesilateli v p°φpad∞ ·sp∞ÜnΘho p°φjmu, pak mß op∞t formu pozice bytu v uva₧ovanΘ lineßrnφ posloupnosti - tentokrßte ale pozice prvnφho bytu, kter² p°φjemce oΦekßvß jako dalÜφ (polo₧ka ACKNOWLEDGEMENT NUMBER). V polo₧ce WINDOW je pak vyjßd°ena velikost datovΘho okΘnka, kterΘ p°φjemce nabφzφ odesilateli, a kterΘ ve svΘ podstat∞ signalizuje, kolik volnΘho mφsta ve svΘ vyrovnßvacφ pam∞ti mß p°φjemce jeÜt∞ k dispozici (viz minul² dφl).

Je dobrΘ si uv∞domit, ke kterΘmu sm∞ru p°enosu se obsah t°φ prßv∞ uveden²ch polo₧ek vztahuje. Uva₧ujeme-li segment, sm∞°ujφcφ od uzlu A do uzlu B, t²kß se jeho polo₧ka SEQUENCE NUMBER p°enosu v tΘm₧e sm∞ru (tj. od A do B), zatφmco potvrzenφ v polo₧ce ACKNOWLEDGEMENT NUMBER se vztahuje k p°enosu dat v opaΦnΘm sm∞ru (tj. od B do A). Stejn∞ tak se i obsah polo₧ky WINDOW t²kß p°enosu dat v opaΦnΘm sm∞ru (od B do A).

NalΘhavß data

Jak jsme si ji₧ takΘ naznaΦili, protokol TCP nabφzφ svΘ p°enosovΘ slu₧by ve form∞ proudu (stream) jednotliv²ch byt∙ - odesilatel na jednΘ stran∞ zadßvß k odeslßnφ postupn∞ jednotlivΘ byty, a p°φjemce si je na druhΘ stran∞ ve stejnΘm po°adφ vyzvedßvß. Lze si tedy p°edstavit, ₧e protokol TCP implementuje pomyslnou rouru, do kterΘ odesilatel z jednΘ strany jednotlivΘ byty vklßdß, a p°φjemce si je z druhΘ strany zase odebφrß. Uvnit° tΘto roury se vÜak m∙₧e nachßzet nezanedbateln² poΦet byt∙, kterΘ ji₧ byly odeslßny, ale nebyly dosud p°ijaty. A to m∙₧e u n∞kter²ch aplikacφ zp∙sobovat nemalΘ problΘmy. Nap°φklad p°i vzdßlenΘm p°φstupu pomocφ terminßlovΘ emulace se uvnit° pomyslnΘ roury nachßzφ znaky, kterΘ u₧ivatel ji₧ zadal z klßvesnice, ale kterΘ jeÜt∞ nebyly hostitelsk²m poΦφtaΦem p°ijaty a zpracovßny. Pot°ebuje-li vÜak u₧ivatel nßhle zadat vhodn² povel k p°eruÜenφ prßv∞ probφhajφcφ Φinnosti (tzv. break), musely by p°φsluÜnΘ °φdφcφ znaky postupn∞ projφt rourou a mohly by se uplatnit a₧ teprve tehdy, kdy₧ budou zpracovßny vÜechny p°edtφm zadanΘ znaky.

Protokol TCP vÜak prßv∞ pro tyto ·Φely nabφzφ mo₧nost "p°edbφhßnφ", dovolujφcφ vyslat p°φsluÜnΘ povely jako tzv. nalΘhavß data (urgent data), n∞kdy oznaΦovanß tΘ₧ jako data mimo po°adφ (out-of-band data). P°φznak toho, ₧e dan² segment obsahuje nalΘhavß data, je vyjßd°en nastavenφm p°φsluÜnΘho bitu v polo₧ce CODE BITS. Vlastnφ nalΘhavß data pak musφ b²t umφst∞na od zaΦßtku datovΘ Φßsti segmentu, a v polo₧ce URGENT POINTER je ukazatel na jejich konec v rßmci danΘho segmentu.

Po doruΦenφ nalΘhav²ch dat by m∞l b²t koncov² p°φjemce neprodlen∞ upozorn∞n na jejich existenci. Samotn² protokol TCP vÜak ji₧ nestanovuje, jak²m zp∙sobem se tak mß dφt. Ostatn∞ ani dost dob°e nem∙₧e, nebo¥ p°φsluÜn² mechanismus zßvisφ na konkrΘtnφ implementaci. DalÜφ °φdφcφ bity v ÜestibitovΘ polo₧ce CODE BITS pak slou₧φ mj. pot°ebßm navazovßnφ a ruÜenφ spojenφ, operaci push, umo₧≥ujφ zneplatnit polo₧ku ACKNOWLEDGEMENT NUMBER atd.

Segment ani jeho hlaviΦka nemajφ pevnou dΘlku

Velikost datovΘ Φßsti segmentu, a tφm i segmentu jako takovΘho, nenφ pevnß, a stejn∞ tak nemusφ b²t stejn∞ velkΘ ani segmenty, p°enßÜenΘ postupn∞ v rßmci tΘho₧ spojenφ. Celkovß dΘlka segmentu (tj. jeho datovΘ Φßsti i hlaviΦky) p°itom nenφ vyjßd°ena p°φmo v segmentu samotnΘm, ale a₧ v jeho pseudohlaviΦce (polo₧ka TCP LENGTH).

Otßzkou ovÜem je, jak volit optimßlnφ velikost segmentu. Zde je nutnΘ si uv∞domit, ₧e jednotlivΘ segmenty jsou vklßdßny do IP datagram∙, a ty zase do rßmc∙ (na ·rovni rßmc∙ vrstvy sφ¥ovΘho rozhranφ) - ka₧d² z nich si ale k "u₧iteΦn²m" dat∙m p°idßvß svß °φdφcφ data, kterß p°edstavujφ re₧ii p°enosu. V p°φpad∞ mal²ch segment∙ je tato re₧ie relativn∞ velkß, zatφmco v p°φpad∞ velk²ch segment∙ dochßzφ k fragmentaci, kdy₧ nelze umφstit celΘ segmenty resp. IP datagramy do p°enosov²ch rßmc∙. Optimßlnφ by byl co nejv∞tÜφ segment, p°i kterΘm jeÜt∞ nebude dochßzet k ₧ßdnΘ fragmentaci. Najφt jeho velikost je ale velmi netrivißlnφ (tato velikost toti₧ zßvisφ na mnoha faktorech, kterΘ se navφc mohou dynamicky m∞nit). Samotn² protokol TCP neobsahuje ₧ßdn² mechanismus pro nalezenφ optimßlnφ velikosti segmentu.

Co vÜak protokol TCP nabφzφ, je prost°edek, pomocφ kterΘho se ob∞ strany mohou dohodnout alespo≥ na maximßlnφ velikosti p°enßÜen²ch segment∙. Implicitn∞ pou₧φvß TCP maximum, kterΘ odpovφdß datovΘ Φßsti segmentu o velikosti 536 byt∙ (tak, aby se segment vΦetn∞ svΘ obvyklΘ hlaviΦky veÜel do IP datagramu implicitnφ velikosti 576 byt∙). Tato implicitnφ hodnota je zalo₧ena spφÜe na pesimistickΘm p°edpokladu, ₧e spojenφ mezi ob∞ma koncov²mi ·Φastnφky nenφ p°φmΘ, ale vede p°es jednu Φi n∞kolik bran, a mß malou propustnost. Pokud jsou vÜak oba koncovφ ·Φastnφci p°ipojeni nap°φklad k tΘmu₧ segmentu rychlΘ lokßlnφ sφt∞, je jist∞ ₧ßdoucφ, aby pln∞ vyu₧φvali jejφ v∞tÜφ Üφ°ku p°enosovΘho pßsma a jejφ schopnost p°enßÜet najednou v∞tÜφ bloky dat. Tedy volit v∞tÜφ maximßlnφ velikost segment∙.

KonkrΘtnφ mechanismus pro stanovenφ maximßlnφ velikosti segmentu vyu₧φvß volitelnΘ polo₧ky OPTIONS v hlaviΦce segmentu. Je-li ovÜem tato polo₧ka volitelnß, stejn∞ tak jako je prom∞nnß jejφ dΘlka, nem∙₧e mφt pevnou dΘlku ani samotnß hlaviΦka TCP segmentu. KonkrΘtnφ velikost hlaviΦky (rozÜφ°enΘ v²plnφ ze sam²ch nul na nßsobek 16 bit∙) je pak vyjßd°ena v polo₧ce HLEN.