Konce spojení (“odesilatel” a “adresát”) jsou určeny tzv. číslem portu. Toto číslo je dvojbajtové, takže může nabývat hodnot 0 až 65535. U čísel portů se často vyjadřuje okolnost, že se jedná o porty protokolu TCP tím, že se za číslo napíše lomítko a název protokolu (tcp). Pro protokol UDP je jiná sada portů něž pro protokol TCP (též 0 až 65535), tj. např. port 53/tcp nemá nic společného s portem 53/udp.
Cílová aplikace je v Internetu adresována (jednoznačně určena) IP-adresou, číslem portu a použitým protokolem (TCP nebo UDP). Protokol IP dopraví IP-datagram na konkrétní počítač. Na tomto počítači běží jednotlivé aplikace. Podle čísla cílového portu operační systém pozná které aplikaci má TCP-segment doručit.
Obr. 9.1 Porty TCP a UDP
Základní jednotkou přenosu v protokolu TCP je TCP segment.TCP segment se vkládá do IP-datagramu. IP-datagram se vkládá do linkového rámce. Použije-li se příliš velký TCP-segment, který se celý vloží do velkého IP-datagramu, který je vetší než maximální velikost přenášeného linkového rámce (MTU), pak IP protokol musí provést fragmentaci IP-datagramu (viz obr 9.2).
Obr. 9.2 Segmentace a fragmentace
Zdrojový port (source port) je port odesilatele TCP segmentu, cílový port (destination port) je portem adresáta TCP segmentu. Pětice: zdrojový port, cílový port, zdrojová IP-adresa, cílová IP-adresa a protokol (TCP) jednoznačně identifikuje v daném okamžiku spojení v Internetu.
TCP segment je část z toku dat tekoucích od odesilatele k příjemci. Pořadové číslo odesílaného bajtu je pořadové číslo prvního bajtu TCP segmentu v toku dat od odesílatele k příjemci (TCP segment nese bajty od pořadového čísla odesílaného bajtu až do délky segmentu). Tok dat v opačném směru má samostatné (jiné) číslování svých dat. Jelikož pořadové číslo odesílaného bajtu je 32 bitů dlouhé, tak po dosažení hodnoty 232-1 nabude cyklicky opět hodnoty 0. Číslování obecně nezačíná od nuly (ani od nějaké určené konstanty), ale číslování by mělo začínat od náhodně zvoleného čísla. Vždy když je nastaven příznak SYN, tak operační systém odesilatele začíná znovu číslovat, tj. vygeneruje startovací pořadové číslo odesílaného bajtu, tzv. ISN (Initial Sequence Number).
Naopak pořadové číslo přijatého bajtu vyjadřuje číslo následujícího bajtu, který je příjemce připraven přijmout, tj. příjemce potvrzuje, že správně přijal vše až do pořadového čísla přijatého bajtu mínus jedna.
Délka záhlaví vyjadřuje délku záhlaví TCP segmentu v násobcích 32 bitů (4 bajtů) - podobně jako u IP-záhlaví.
Délka okna vyjadřuje přírůstek pořadového čísla přijatého bajtu, který bude příjemcem ještě akceptován (viz kapitola 9.7).
Ukazatel naléhavých dat může být nastaven pouze v případě, že je nastaven příznak URG. Přičte-li se tento ukazatel k pořadovému číslu odesílaného bajtu, pak ukazuje na konec úseku naléhavý dat. Odesilatel si přeje, aby příjemce tato naléhavá data přednostně zpracoval. Tento mechanismus používá např. protokol Telnet.
V poli příznaků mohou být nastaveny následující příznaky:
Kontrolní součet IP-záhlaví se počítá pouze ze samotného IP-záhlaví. Z hlediska zabezpečení integrity přenášených dat je důležitý kontrolní součet v záhlaví TCP-segmentu počítaný i z přenášených dat. Tento kontrolní součet se počítá nejen ze samotného TCP segmentu, ale i z některých položek IP-záhlaví. Kontrolní součet vyžaduje sudý počet bajtů, proto v případě lichého počtu se data fiktivně doplní jedním bajtem na konci.
Obr. 9.5 Pole ze kterých
se počítá kontrolní součet TCP záhlaví
Kontrolní součet se počítá
z polí znázorněných na obrázku 9.5. Tato struktura slouží pouze pro výpočet
kontrolního součtu – v každém případě se žádná takováto struktura nepřenáší
Internetem! Někdy se tato struktura označuje jako pseudozáhlaví.
Obr. 9.6 IP a TCP záhlaví
Volitelná položka se skládá z typu volitelné položky, délky volitelné položky a hodnoty. Délka TCP záhlaví musí být dělitelná čtyřmi. V případě, že délka záhlaví by nebyla dělitelná čtyřmi, pak se záhlaví doplňuje prázdnou volitelnou položkou – NOP.
Jelikož pole délka záhlaví je pouze 4 bity dlouhé, tak toto pole může nabývat maximálně hodnoty 11112= 1510. Délka záhlaví se udává v násobcích čtyř, tudíž záhlaví může být dlouhé maximálně 15x4=60 bajtů. Povinné položky zaberou 20 bajtů, takže na volitelné zbývá nejvýše 40 bajtů.
Některé volby TCP záhlaví
včetně jejich struktury jsou uvedeny na obrázku 9.7.
Obr. 9.7 Některé volitelné
položky TCP záhlaví
Protokol TCP využívá k transportu dat Internetem protokol IP, avšak nad tímto protokolem zřizuje spojovanou službu. Musí řešit problémy navázání a ukončení spojení, potvrzování přijatých dat, vyžádání ztracených dat, ale také problémy průchodnosti přenosové cesty. Popis TCP segmentu je tedy jen malou částí TCP protokolu, podstatně rozsáhlejší částí je popis výměny TCP segmentů (handshaking) mezi oběma konci TCP spojení.
Obr. 9.8 Navazování spojení
Obr. 9.9 Stavy při navazování
spojení
Obr. 9.10 Ukončování
spojení
Obr. 9.11 Stavy při uzavírání
spojení
Obr. 9.12 Stisk kláves A a H
Je vcelku pochopitelné, že je snaha objem přenášených dat zmenšit, čímž se snažíme zabránit ucpání přenosových cest. Myšlenka spočívá v tom, že potvrzování přijatých dat nebude probíhat okamžitě, ale se zpožděním. Během tohoto zpoždění se pak mohou objevit i další data k přenosu.
Princip spočívá v tom, že operační systém spustí pro tento účel hodiny zpravidla s tikem 200 ms (délka tiku musí být pod 500 ms). Po každém tiku systém zkontroluje, zda-li není něco k odeslání (potvrzení přijatých dat či odeslání dat). Pokud je třeba něco odeslat, pak vše odešle najednou.
Na obrázku 9.13 server přijal znak A – segment (1), ale bude odpovídat až s dalším 200 ms tikem. Do té doby aplikace stihne i připravit data k odeslání (echo A). Operační systém jedním TCP segmentem (segment (2)) provede potvrzení znaku A a zároveň odešle echo A.
Jenže je již málo pravděpodobné,
že klient stiskne další klávesu H tak aby software klienta byl schopen
znak H odeslat společně s potvrzením přijetí echa klávesy A. Proto jak
je z následujícího obrázku patrné klient provede potvrzení echa klávesy
A pomocí segmentu (3) a stisk klávesy H způsobí vyslání dalšího TCP segmentu
(4).
Obr. 9.13 Zpoždění 200
ms
V ideálním případě dojde k redukci přenášených TCP segmentů ze čtyřech na tři. Ještě větší úspory přinese použití Nagleova algoritmu znázorněného na obrázku 9.14.
Obr. 9.14 Nagleův algoritmus
V tomto případě software
klienta nečeká na další tik (200 ms), ale čeká až dojdou nějaká data od
protější strany. Tento algoritmus vyrovnává dobu odezvy vůči kapacitě přenosové
linky (řídí tok dat). Tj. je-li linka více zatížena, pak je na ní delší
odezva a odpověď se také pozdrží.
Představme si (obr. 9.15), že klient se serverem navázal spojení a vzájemně se dohodli na maximální velikosti segmentu (MSS) o velikosti 1K (tj. 1024 B) a vzájemné velikosti okna 4K (tj. 4096B).
Obr. 9.15 Technika okna
Klient začne s odesíláním dat, odešle segmenty 1, 2 a 3. Poté obdrží od serveru potvrzení (4), které potvrzuje segmenty 1 a 2. Klient v zápětí odesílá segmenty 5, 6 a 7. Jenže server data mezitím nedokázal zpracovat a data mu zaplnila vyrovnávací paměť, proto segmentem 8 sice potvrdí příjem segmentů 3, 5, 6 a 7, ale zároveň klientovi uzavře okno, tj. klient nemůže s odesíláním dat pokračovat. Poté co server zpracuje část dat (2 KB), tak umožní klientovi pokračovat v odesílání, ale neotevře mu segmentem 9 okno celé – pouze 2KB, protože všechna data ve vyrovnávací paměti ještě nezpracoval a pro více dat nemá místo.
Obr. 9.16 Okno
Obr. 9.17 Zahlcení
Ztráta dat je vždy nepříjemná. Snahou je se ztrátě dat vyhnout. Na straně odesilatele se proto také zavádí okno. Toto okno se snaží specifikovat, kolik může odesilatel odeslat nepotvrzených dat aniž by došlo k zahlcení sítě. Toto okno na straně odesilatele se anglicky nazývá Congestion Window (zkratkou CWND). Odesilatel postupně zvyšuje CWND. CWND však nelze zvyšovat neomezeně. Hranice za kterou už je větší pravděpodobnost zahlcení se označuje SSTHRESH. Internet však budeme chtít využívat maximálně, tj. budeme chtít najít největší použitelné CWND (to bude někde nad SSTHRESH). SSHTRESH má smysl udržovat pouze v násobcích velikosti odesílaného segmentu (MSS).
Odesilatel odesílá vždy jen takové množství nepotvrzených dat, které nepřevyšuje okno inzerované příjemcem (WINDOW) ani nepřevyšuje CWND, tj. odesílá jen nejvýše min(WINDOW,CWND) nepotvrzených dat.
Pochopitelně, že po několika krocích se odesilatel dostane do situace, kdy síť zahltí a potvrzení nedostane, tj. musí opakovat odesílání segmentů, protože se segment ztratil. V takovém okamžiku se CWND zmenší na polovinu a tato hodnota se také nastaví do veličiny SSTHRESH (pokud by SSTRESH mělo být menší než dva segmenty, pak se nastaví na velikost dvou segmentů).
Je třeba rozlišovat jakým způsobem byl zjištěn stav, že segment nebyl potvrzen. Nyní jsme předpokládali, že se segment po cestě k příjemci ztratil. Příjemce segment nedostal a tak stále potvrzuje předchozí (přijatý) segment. Po třech zopakovaných potvrzeních předchozího přijatého segmentu se segment považuje za ztracený a odesilatel jej opakuje. Může však nastat situace, že odesilatel ve stanoveném časovém intervalu nedostane vůbec žádné potvrzení (ani žádného předchozího segmentu). V takovém případě se CWND nastaví na velikost jednoho segmentu (MSS) a SSTHRESH na dvojnásobek velikosti segmentu (2x MSS) a začne se s pomalým startem od počátku.
Odesilatel v okamžiku odesílání segmentu nemůže meditovat nad tím co má udělat, ale musí se rozhodnout rychle na základě udržovaných proměnných:
Obr. 9.19 Vyhýbání se zahlcení
V případě, že CWND je značně velké (může být řádově i MB či dokonce GB), pak opakování celého nepotvrzeného okna v případě ztráty jednoho segmentu by bylo velice nepříjemné, protože by enormně zvyšovalo režii. Je proto snaha využít tzv. algoritmus rychlého zopakování.
Jak však odesilatel zjistí, že došlo ke ztrátě TCP segmentu? (Nyní se již nebude zmiňovat o případu, že odesilatel nedostává od příjemce potvrzováno vůbec nic.) Příjemce zjistí, že došlo ke ztrátě segmentu tím, že dostává další segmenty (a ztracený segment stále nedochází). Tj. chybí mu data v posloupnosti přijímaných dat. Přicházejí mu tedy segmenty mimo pořadí. Příjemce je povinen v případě přijetí segmentu mimo pořadí zopakovat (duplikovat) potvrzení posledního správně přijatého segmentu.
Jenže TCP segmenty jsou zabaleny do IP-datagramu. Každý IP-datagram putuje Internetem samostatně a teoreticky jinou cestou. Některé cesty jsou rychlejší a jiné pomalejší. Může se stát, že segment putoval pomalejší cestou a přirozeně dorazil později než následující segment. Mezitím však příjemce již provedl odeslání duplikovaného potvrzení.
Přijetí jedné duplikované odpovědi je proto bráno vcelku za běžnou záležitost. Jiná je situace, když se segment opravdu ztratil. Příjemce pak segment nedostal a dostal následující segment. Provedl duplikaci potvrzení posledního správně přijatého segmentu. Poté však dostane ještě následující segment, ten je však také mimo pořadí, protože příjemce ještě neobdržel ztracený segment. Opět provede duplikaci. Příjemce obdrží opět další segment, který je rovněž mimo pořadí – zopakuje duplikaci atd.
Odesilatel pak od příjemce postupně dostává první duplikát, druhý duplikát a stále si říká, že to je vcelku normální. Po obdržení třetího duplikátu si však řekne: “To už se opravdu muselo něco stát, zopakuji mu segment o kterém se příjemce domnívá, že je ztracen” a provede zopakování ztraceného segmentu. Příjemce obdrží ztracený segment. Avšak jelikož příjemce nezahodil žádný z následujících segmentů (původně přijatých mimo pořadí), tak potvrdí přijetí všech přijatých segmentů.
Tento algoritmus rychlého zopakování umožňuje zopakovat pouze ztracený segment a nikoliv nutnost opakování všech nepotvrzených dat. Opakování všech nepotvrzených dat je nutné pouze v případě, že se algoritmus rychlého opakování nestihne v zadaném časovém intervalu.
Jak je to v případě rychlého zopakování s proměnnýcmi CWND a SSTHRESH?