Část XII. Transportní vrstva
Transportní vrstva je první vrstvou, se kterou se setkáme pouze v koncových uzlech sítě, ale nikoli v jejích vnitřních uzlech (směrovačích). Však také hlavním úkolem transportní vrstvy je zajišťovat vzájemnou komunikaci koncových uzlů (tzv. komunikaci end-to-end). Je také první vrstvou, která v rámci uzlu rozlišuje jednotlivé entity (procesy) prostřednictvím tzv. portů. Nižší vrstvy se na jednotlivé uzly dívají vždy jako na dále nedělitelný celek.
našem průchodu sedmi vrstvami referenčního modelu ISO/OSI jsme se dostali až na úroveň vrstvy transportní. Ta je v rámci RM ISO/OSI čtvrtou v pořadí, ať již vrstvy počítáme "zdola", nebo "shora". Na transportní vrstvu se přitom můžeme dívat jako na jakousi přizpůsobovací vrstvu mezi trojicí nižších vrstev, orientovaných na přenos dat (vrstev fyzické, linkové a síťové), a trojicí vyšších vrstev, orientovaných už spíše na aplikace a jejich podporu. Naznačuje to ostatně i dnešní první obrázek.
V rámci síťového modelu TCP/IP transportní vrstva samozřejmě existuje také, ale je teprve druhou (počítáno shora), resp. třetí vrstvou (zdola). Jde o důsledek skutečnosti, kterou bychom měli dobře znát již z předchozích dílů tohoto seriálu: zatímco referenční model ISO/OSI má sedm vrstev, TCP/IP má pouze vrstvy čtyři. A také si s nimi vystačí. Navíc svou nejnižší vrstvu, vrstvu síťového rozhraní, TCP/IP samo nijak nedefinuje (ale používá řešení pocházející odjinud).
Ani menší počet vrstev v TCP/IP však nemění nic na tom, že transportní vrstva je první vrstvou (počítáno odspodu), která je přítomná až v koncových uzlech a nikoli ve vnitřních uzlech sítě (ve směrovačích). Vzhledem k tomu má na starosti vzájemnou komunikaci koncových uzlů, pro kterou se i češtině vžilo označení, pocházející z angličtiny: komunikace end-to-end (doslova: komunikace "konec-konec").
Aby se transportní vrstva mohla soustředit na vzájemnou komunikaci koncových uzlů, umožňuje bezprostředně nižší vrstva vrstva síťová. Ta má na starosti hledání vhodných cest v síti, resp. v soustavách vzájemně propojených sítí (přes jednotlivé směrovače), a samozřejmě i doručování dat po takových cestách. Tím vlastně vytváří iluzi (určenou transportní vrstvě), že všechny koncové uzly jsou mezi sebou propojeny přímo, "každý s každým". Transportní vrstva se pak již může soustředit na další aspekty toho, jak si koncové uzly vzájemně vyměňují (předávají) data a komunikují mezi sebou. Ale jaké aspekty to vlastně jsou? Co přesně transportní vrstva dělá?
To záleží i na tom, co a jak nabízí a poskytuje vrstva síťová a co a jak na tom má či nemá transportní vrstva měnit, zda k tomu má něco přidávat, a co... atd.
Síťová vs. transportní vrstva ISO/OSI
Referenční model ISO/OSI a síťový model TCP/IP se liší i v tom, jakou mají představu o fungování své síťové vrstvy. RM ISO/OSI má blíže k "telekomunikačnímu paradigmatu", v jehož rámci vítězí představa inteligentní a na funkce bohaté sítě ("chytré sítě") a třeba i jednoduchých ("hloupých") koncových uzlů. Součástí této představy je i to, že přenosy dat na všech úrovních (vrstvách) by měly probíhat spojovaným způsobem, tedy s navazováním spojení mezi odesilatelem a příjemcem. Dále představa, že přenosy dat na jednotlivých vrstvách by měly být řešeny jako spolehlivé a tedy by se měly starat o nápravu toho, co se pokazí případné ztrát dat či výpadky spojení. Ovšem ne vždy bude tato náprava dokonalá (stoprocentní). Proto se počítá s tím, že bude pokračovat i na vyšších vrstvách, které se také budou snažit o zajištění (lepší, resp. vyšší) spolehlivosti.
Autoři ISO/OSI přitom správně předpokládali, že jejich síťová vrstva bude nasazována v různém prostředí, které se liší četností výpadků spojení a ztrát dat. Například v prostředí lokálních sítí, kde asi lze očekávat relativně málo podobných výpadků a ztrát. Nebo v prostředí veřejných datových sítí, kde mohou nastat nějaké výpadky spojení, ale data by se ztrácet neměla. A stejně tak v prostředí rozlehlých sítí, kde se data mohou ztrácet relativně častěji, stejně tak může častěji vypadávat spojení.
Kvůli tomu se autoři ISO/OSI rozhodli zavést tři různé varianty (kategorie) síťových protokolů:
kategorie A pro prostředí, kde dochází k minimálním (žádným) ztrátám paketů a minimálním (žádným) výpadkům spojení,
kategorie B pro minimální (žádné) ztráty paketů a občasné výpadky spojení,
kategorie C pro prostředí, kde dochází k občasným ztrátám paketů a občasným výpadkům spojení.
Od transportní vrstvy se pak ve světě ISO/OSI očekává, že bude zachovávat spojovaný způsob fungování a také že se bude snažit ještě lépe kompenzovat možné výpadky spojení a ztráty dat. Dokonce se od ní očekává i určitá optimalizace ve smyslu, že se může snažit navazovat více transportních spojení přes jedno jediné síťové spojení. Motivace pro tuto optimalizaci pochází z prostředí veřejných datových sítí, kde se platilo za zřizování každého jednotlivého (síťového) spojení. Takže schopnost využít jedno spojení pro více spojení transportních mohla snížit náklady.
Celkově pak transportní vrstva ISO/OSI předpokládala pět různých variant (tříd) transportních protokolů, označovaných TP0 až TP4:
třída TP0 je pouze jednoduchou nadstavbou nad síťovým protokolem kategorie A, nemění jeho vlastnosti,
třída TP1 je nadstavbou nad síťovým protokolem kategorie B, omezuje případné výpadky spojení,
třída TP2 je nadstavbou nad A, dokáže využít jedno síťové spojení pro více transportních spojení,
třída TP3 je nadstavbou nad B, omezuje případné výpadky spojení a dokáže využít jedno síťové spojení pro více transportních spojení,
třída TP4 je nadstavbou nad C, omezuje případné výpadky spojení a ztráty paketů.
Celou představu ilustruje další obrázek.
Síťová vs. transportní vrstva TCP/IP
Ve světě TCP/IP se uplatňuje "počítačové" paradigma, volající po "hloupé síti a chytrých uzlech". Tedy po maximálním zefektivnění přenosové části sítě, která bude nabízet jen minimum funkcí v co nejjednodušším provedení (proto "hloupá síť"), ale zato je bude realizovat velmi efektivně (rychle). O všechno ostatní, pokud je to vůbec požadováno, by se měly starat až koncové uzly na úrovni transportní (nebo aplikační) vrstvy, nikoli přenosová část sítě (na úrovni vrstvy síťové).
Konkrétním příkladem toho, co je ve světě TCP/IP považováno za něco "ne zcela nezbytného", čím by se síťová vrstva neměla zatěžovat a zpomalovat, je zajištění spolehlivosti přenosů. Tedy kompenzace (náprava) případných ztrát paketů, pokud k nim vůbec dojde. Je-li vůbec spolehlivost přenosů požadována, měly by si ji zajistit koncové uzly samy. Vzhledem k celému paradigmatu ("hloupá síť, chytré uzly") k tomu mají lepší předpoklady než síť jako taková, resp. její síťová vrstva.
Dalším rozdíl oproti ISO/OSI spočívá v tom, že v TCP/IP se na úrovni síťové vrstvy jednoznačně preferuje nespojovaný způsob fungování, tedy bez navazování spojení mezi odesilatelem a příjemcem. To přináší významný důsledek v tom, že nemůže docházet k žádným výpadkům spojení (když žádné takové ani není navazováno). A také není třeba (na síťové vrstvě) ani žádné takové výpadky kompenzovat.
Společným důsledkem obou výše uvedených skutečností (preference nespolehlivé a nespojované komunikace na úrovni síťové vrstvy) je pak to, že TCP/IP nepotřebuje rozlišovat různé kategorie síťových přenosových protokolů jako RM ISO/OSI (viz jeho kategorie A, B a C). Místo toho si vystačí jen s jediným síťovým protokolem, a to s protokolem IP. Snad netřeba už tolik zdůrazňovat, že funguje nespojovaně a nespolehlivě a že dokáže fungovat snad v jakémkoli prostředí (nad jakoukoli přenosovou technologií linkové vrstvy, resp. vrstvy síťového rozhraní).
V TCP/IP pak nad takto koncipovanou síťovou vrstvou existuje transportní vrstva, která nabízí dva různé transportní protokoly (místo pěti v ISO/OSI). Liší se v tom, zda zachovávají celkový způsob fungování síťového protokolu IP (tedy jeho nespojovaný a nespolehlivý charakter komunikace), nebo zda se jej snaží měnit na spojovaný a spolehlivý. S oběma takto koncipovanými transportními protokoly jsme se už v předchozích dílech setkali:
protokol UDP (User Datagram Protocol) je pouze jednouchou nadstavbou nad protokolem IP a stejně jako on funguje nespojovaně a nespolehlivě,
protokol TCP (Transmission Control Protocol) je už složitější nadstavbou nad protokolem IP a mění jeho způsob fungování na spojitý a spolehlivý.
Logika existence dvou transportních protokolů, které jsou vzájemně alternativní, spočívá v tom, že aplikace si mohou samy svobodně vybrat, který z nich chtějí používat. Například "klasické" počítačové aplikace, jako například přenos souborů, elektronická pošta atd., preferují spolehlivost a dávají přednost protokolu TCP. Naproti tomu novější multimediální aplikace dávají přednost spíše protokolu UDP, protože ten se nezdržuje zajišťováním spolehlivosti a dokáže tak přenášet data rovnoměrněji a s menší prodlevou (latencí) než protokol TCP. Příklad preferencí některých aplikací naznačuje další obrázek.
Další úkol transportní vrstvy
Transportní vrstva má obecně (v RM ISO/OSI i v TCP/IP) ještě další úkoly kromě toho, co jsme si popisovali v předchozích odstavcích. Vlastně jsme to naznačili již v perexu: transportní vrstva je první vrstvou (měřeno "odspodu"), která se již nedívá na jednotlivé uzly jako na dále nedělitelné celky, ale rozlišuje v nich jednotlivé entity, které vystupují buď jako příjemci, nebo jako odesilatelé dat.
Abychom si trochu přiblížili, o co vlastně jde: na jednom počítači může běžet několik aplikací, které komunikují s dalšími uzly v síti, a to nezávisle na sobě. Například uživatel může mít na svém osobním počítači puštěný WWW browser, s nímž právě brouzdá báječným světem internetu. Vedle toho má puštěného i klienta elektronické pošty, jímž přijímá svou elektronickou korespondenci. Tím výčet možností samozřejmě zdaleka nekončí, ale pro nástin podstaty problému stačí alespoň dva různé běžící programy, resp. aplikace. Představme si totiž, co se má stát v okamžiku, kdy uživatelův počítač přijme nějaká data. Komu mají být předána? Webovému browseru? Nebo poštovnímu klientovi? Jistě by to mělo záviset na tom, zda přijatá data představují nějakou WWW stránku, zprávu elektronické pošty, nebo třeba soubory, přenášené prostřednictvím protokolu FTP či ještě něco jiného. Ale kdo by to měl zkoumat, a podle čeho?
Síťová vrstva takové otázky neřeší. Pro ni je každý uzel sítě nadále nedělitelný celek. Takže když přijme nějaká data pro daný uzel, nezajímá se o to, komu (které aplikaci) patří, vždy je předá své bezprostředně vyšší vrstvě vrstvě transportní. Teprve transportní vrstva pak má za úkol rozlišovat, komu v rámci daného počítače přijatá data patří a předat je právě a pouze jemu. Obdobně vše probíhá při odesílaní, kdy transportní vrstva přijímá data zde také rozlišuje, od koho jsou (a tuto informaci musí vhodným způsobem zachovat pro koncového příjemce dat).
Můžeme si to celé představit také tak, že síťová vrstva vytváří přenosový kanál, který je společně využíván všemi odesilateli, resp. příjemci na daném uzlu s tím, že až transportní vrstva zajišťuje na straně odesilatele potřebné "sloučení" (multiplex) dat od různých odesilatelů do jednoho datového toku, na straně příjemce pak zase potřebné "rozbočení" (demultiplex) těchto dat podle toho, komu jsou určena. Vše naznačuje i obrázek, který je oproti obvyklým konvencím jakoby pootočen o 90 stupňů.
Jinou představu téhož ukazuje i další obrázek, na kterém již lze názorně ukázat jeden významný aspekt, týkající se adresování. Je opět společný pro RM ISO/OSI i TCP/IP a týká se adresování na úrovni transportní vrstvy.
Porty a body SAP
Jak již víme, na úrovni síťové vrstvy se používají síťové adresy (v TCP/IP tzv. IP adresy), které identifikují jednotlivé uzly jako celky. Přesněji: identifikují jedno síťové rozhraní, s tím, že některé uzly (například směrovače) jich mohou mít více. Rozhodně ale tyto síťové adresy nerozlišují jednotlivé příjemce a odesilatele v rámci daného uzlu.
Rozlišování jednotlivých příjemců a odesilatelů má na starosti až transportní vrstva. K tomu také musí používat nějaké konkrétní adresy (transportní adresy), které by měly mít relativní charakter (měly by se vztahovat jen k danému uzlu, resp. rozlišovat jen v rámci tohoto uzlu). Jak by ale tyto transportní adresy měly vypadat?
Problém spočívá v tom, že na různých systémových platformách (například v prostředí MS Windows, Unixu, Linuxu, MAC OS a dalších) mohou být odesilatelé a příjemci obecně různého typu mohou to být různé procesy, případně systémové úlohy, vlákna, nebo třeba i rezidentní programy (ještě ve starém MS DOSu). Jejich identifikace v rámci příslušné platformy se může diametrálně lišit. Někdy mohou být identifikováni čísly, jindy znakovými identifikátory apod. Hlavně ale příslušné entity (procesy, úlohy atd.) vznikají a zase zanikají dynamicky. Takže není dopředu jasné, kdo (jaký proces, úloha atd.) bude kde existovat a měl by přijímat data, určená například WWW serveru (nebo poštovnímu serveru apod.).
Všimněte si jedné věci: na straně příjemce nejde ani tak o to, kdo je ten, co nějaká data přijímá, jako spíše o to, že "ten někdo" poskytuje určitou službu a tudíž přijímá data, určená poskytovateli příslušné služby. Tomu, kdo je v roli klienta (např. WWW klienta a vznáší požadavek na nějakou WWW stránku), může být celkem jedno, jaký konkrétní proces na druhé straně plní roli WWW serveru. Důležité pro něj je, aby někdo takový existoval, fungoval a aby klient věděl, kam mu poslat svůj požadavek. Takže by se vlastně hodila spíše nějaká adresace ve stylu "příjemcem je ten, kdo poskytuje službu AB", místo adresace ve smyslu "příjemcem je proces s identifikátorem XY". A tak to také v praxi (ve světě RM ISO/OSI i TCP/IP) skutečně chodí.
Příslušné adresování, používané na úrovni transportní vrstvy, však není založeno přímo na představě poskytovatelů služeb. To by nemuselo být až tak šikovné a třeba by to bylo někdy i omezující. Místo toho je použit jiný koncept, založený na představě "přechodových bodů" mezi transportní vrstvou a vrstvou bezprostředně vyšší (což je ISO/OSI relační vrstva, u TCP/IP vrstva aplikační). Tyto přechodové body jsou určitou abstrakcí, kterou je nejlepší přirovnat k vyrovnávací paměti (bufferu) s režimem fronty: z jedné strany se do přechodového bodu určitá data vkládají (zapisují), z druhé strany se z ní ve stejném pořadí vyjímají (čtou). Představu ilustruje obrázek.
Přechodové body jsou obecně obousměrné (lze si je představit jako dvě samostatné fronty s opačným "směrem"). V prostředí RM ISO/OSI se jim říká "body přístupu ke službám" (SAP, Service Access Points), ale známější asi jsou pod svým označením z prostředí TCP/IP, kde se o nich mluví jako o portech.
Porty vs. procesy
Výhodou portů (přechodových bodů SAP) je tedy to, že jsou abstrakcí a jako takové mohou být všude (na všech platformách) stejné. To má zásadní výhodu v tom, že s jejich existencí je pak možné počítat "dopředu" (apriori), stejně jako s tím, že mají stejné vlastnosti. Konkrétní způsob jejich realizace na každém jednotlivém uzlu sítě naopak může zůstat skryt.
Jednotné (všude stejné) může být i označení portů, resp. bodů SAP, a tím i jejich adresování (na úrovni transportní vrstvy). V prostředí TCP/IP jsou jednotlivé porty adresovány skrze pořadová čísla. Přesněji: pomocí celých nezáporných čísel (0, 1, 2, 3, 4 atd.). V praxi se pak hovoří o číslech portů. Třeba o portu číslo 80, o portu 25 apod. Takže transportními adresami (relativními adresami na úrovni transportní vrstvy) jsou v TCP/IPO právě tato čísla portů.
Důležité ale je uvědomit si, že port (bod SAP) ještě není to samé co proces (úloha, vlákno atd.), které skutečně přijímá a zpracovává nějaká data, nebo je naopak generuje. Port je skutečně jen jakýsi "průchozí bod" (s režimem fronty), za kterým je teprve "schován" příslušný proces (úloha atd.). Ovšem když porty existují "dopředu" (apriori), zatímco aplikační entity (procesy, úlohy) vznikají dynamicky podle momentálních potřeb, musí i jejich vzájemná vazba být dynamická. V praxi to vypadá tak, že když je vytvořen nějaký proces a ten má nějak komunikovat v prostředí sítě, musí se nejprve "sdružit" (asociovat) s některým portem. Teprve pak může odesílat svá data (přes tento port) a také je (přes tento port) přijímat. Protistrana, která s takovým procesem komunikuje, musí znát číslo příslušného portu, svá data pak také adresuje tomuto portu (přesněji na daný cílový uzel, v rámci tohoto cílového uzlu pak příslušnému portu).
Obecně přitom platí, že jeden proces (úloha atd.) může být asociován (sdružen) s více porty. Naopak to ale neplatí: s jedním portem může být sdružen (asociován) nejvýše jeden proces. Důvod je jednoduchý: co by asi takový port dělal, kdyby přijal nějaká příchozí data? Jak by vybíral mezi dvěma (či dokonce více) procesy, jimž by tato data měl předat?
Servery a jejich klienti
Ukažme si nyní na konkrétním příkladu, jak celá představa o portech a procesech zapadá do běžné praxe, kdy spolu v prostředí sítě komunikují aplikace a procesy v roli serverů a jejich klientů. Třeba když si uživatel na svém osobním počítači pustí WWW browser a zadá mu, že chce navštívit nějakou konkrétní stránku, např. na adrese www.earchiv.cz (kde má svůj osobní archiv autor tohoto seriálu). Webový browser si nejprve nechá přeložit symbolické doménové jméno (www.earchiv.cz) na odpovídající IP adresu, na ni pak pošle požadavek na stažení konkrétní stránky (např. index.php3). Na cílovém počítači je ale třeba předat příslušný požadavek procesu, který zde plní roli WWW serveru.
Klient (uživatelův browser) přitom dopředu ví, že takový proces je sdružen (asociován) s portem číslo 80, a tak jej adresuje právě tomuto portu. Proces, který na adrese www.earchiv.cz funguje jako WWW server, tak požadavek dostane a v odpovědi na něj zašle klientovi požadovanou WWW stránku (index.php3). Přitom také musí uvést nějaké číslo portu, na které má být odpověď klientovi doručena. Server tedy standardně posílá svou odpověď na stejný port (na straně klienta), z jakého mu přišel původní požadavek.
Celou situaci s komunikací klienta a serveru názorně ukazuje předchozí obrázek, na němž si můžeme znovu připomenout jiný úkol transportní vrstvy, popisovaným v úvodu: měnit nespolehlivý a nespojovaný způsob komunikace (na úrovni síťové vrstvy, pomocí protokolu IP) na spojovaný a spolehlivý (na úrovni transportní vrstvy, pomocí protokolu TCP), nebo jej ponechávat beze změny jako nespolehlivý a nespojovaný (pomocí protokolu UDP) podle toho, co si vybere příslušná aplikace. Přitom služba World Wide Web (WWW) je příkladem aplikace, která dává přednost spojovanému a spolehlivému přenosu, využívá tedy služeb transportního protokolu TCP.
Jen pro ilustraci si naznačme, jak může jeden WWW server současně poskytovat své služby přes jeden a ten samý port (číslo 80) více klientům. Když mu všichni posílají své požadavky na stejnou adresu (IP adresa, port 80), jak pozná, od koho co pochází a kam má zaslat požadovanou WWW stránku? Odpověď je principiálně jednoduchá a stejná pro všechny druhy serverů: u každého požadavku si pamatují, ze kterého spojení přišel. A toto spojení je obecně určeno pěticí údajů:
transportním protokolem (v případě WWW jde o TCP),
IP adresou a portem na straně klienta,
IP adresou na portem na straně serveru.
Když server dostane dva požadavky od klientů na různých počítačích, liší se příslušná spojení už IP adresou klienta. A pokud by snad šlo o požadavky od dvou různých klientů, běžících na stejném počítači (například když má uživatel puštěny dva browsery, případně jen dvě okna či záložky ve stejném browseru), rozliší je alespoň podle různého čísla portu, použitého na straně klienta. Vše ilustruje obrázek.
V případě, že komunikace mezi klientem a serverem probíhá nespojovaně (prostřednictvím transportního protokolu UDP), je identifikace odesilatelů a příjemců obdobná. Server dokáže rozlišit požadavky různých klientů podle IP adresy a čísla portu (na straně odesilatele), i když zde žádné spojení vůbec nevzniká.
Konvence o tzv. dobře známých portech
Zastavme se na závěr u jedné důležité drobnosti: jak může webový klient (browser) dopředu vědět, že své požadavky má posílat "svému" serveru na port číslo 80? Jak ví poštovní klient, že má odesílanou poštu posílat "svému" serveru na port číslo 25? Jak je to pro ostatní služby a aplikace?
Odpověď je taková, že musí existovat určitá konvence, ve výše naznačeném smyslu, a ta musí být dopředu známá všem, kdo ji potřebují znát. To jsou ti, kteří programují a provozují servery, i ti, kteří píší jejich klienty. Naopak tato konvence nemusí být známa běžným uživatelům. Proč? Například když klient (browser) dostane od svého uživatele pokyn k načtení nějaké konkrétní stránky, automaticky předpokládá, že jej má poslat serveru na port číslo 80, a tak to také dělá. To mu naordinoval (naprogramoval do něj) už jeho autor.
Samozřejmě pokud by uživatel měl jiné přání a explicitně by si vyžádal zaslání svého požadavku na nějaký jiný port (např. na port 8080, pomocí URL ve tvaru http://www.earchiv.cz:8080/index.php3), browser by to respektoval. Ovšem aby takový požadavek mohl být korektně přijat a vyřízen, musel by i na cílovém počítači existovat WWW server, asociovaný s příslušným portem (zde s portem číslo 8080). Při nějakém testování či ladění tomu tak může být, při běžném rutinním provozu to není zvykem (WWW server "sedí" na standardním portu č. 80).
Zpět ale k samotné konvenci o tom, který port je předem vyhrazen čemu: portům, jejichž význam je dopředu stanoven, se v TCP/IP říká příznačně: dobře známé porty (anglicky: well-known ports). Jde obecně o porty v rozsahu od 0 do 1 023, příslušnou konvenci spravuje orgán jménem IANA (Internet Assigned Numbers Autority). Dříve ji publikoval pravidelně (jednou za rok, později každých 6 měsíců) ve formě dokumentu RFC. Dnes je tato konvence zveřejňována již průběžně na WWW stránkách IANA. Konkrétně na adrese http://www.iana.org/assignments/port-numbers. Malou část této konvence vidíte v následující tabulce.