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

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.

Obrázek 60.1.
Obr. 60.1.: Formát TCP segmentu
Nejprve si ale připomeňme (v souladu s 57. dílem), ž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 (viz obr. 56.2 v 56. dílu), 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. Přesný formát segmentu protokolu TCP ukazuje obrázek 60.1.

Čí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 (viz 55. díl), 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>.

Obrázek 60.2.
Obr. 60.2.: TCP segment a jeho pseudohlavička
Jak ovšem vyplývá z obrázku 60.1., 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 (viz obr. 60.2), 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é - stejným způsobem, který jsme si popisovali již v 56. dílu.

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 (viz 57. díl), 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 (viz obr. 60.2., 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 (viz obr. 60.1.). 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.