6. A szállítási réteg



Hasonló dokumentumok
Hálózati architektúrák laborgyakorlat

Számítógépes hálózatok

6.1. A szolgálat minősége ( Quality of Service ) A szolgálatok minőségét az OSI 3 csoportba sorolja: kívánt elfogadható elfogadhatatlan

Kommunikáció. 3. előadás

4. Hivatkozási modellek

Kommunikáció. Távoli eljáráshívás. RPC kommunikáció menete DCE RPC (1) RPC - paraméterátadás. 3. előadás Protokollok. 2. rész

2. fejezet Hálózati szoftver

2. fejezet Hálózati szoftver

Számítógépes hálózatok

Flash és PHP kommunikáció. Web Konferencia 2007 Ferencz Tamás Jasmin Media Group Kft

Dr. Varga Imre Debreceni Egyetem, Informatikai Kar. Socket-programozás. C nyelven, Linux alatt

Számítógépes Hálózatok GY 6.hét

Hálózatok II. A hálózati réteg funkciói, szervezése

Számítógép-hálózatok: 4. Labor. TCP kliens. A gyakorlat célja:

Számítógépes Hálózatok. 5. gyakorlat

Tartalom. Az adatkapcsolati réteg, Ethernet, ARP. Fogalma és feladatai. Adatkapcsolati réteg. A hálókártya képe

Számítógépes Hálózatok GY 7.hét

Számítógépes Hálózatok. 4. gyakorlat

Két típusú összeköttetés PVC Permanent Virtual Circuits Szolgáltató hozza létre Operátor manuálisan hozza létre a végpontok között (PVI,PCI)

Multiprotocol encapsulation (RFC1483) - IETF Classical IP over ATM (RFC1577) - IETF LAN Emulation (LANE) - ATM Forum Multiprotocol over ATM (MPOA) -

UNIX: folyamatok kommunikációja

COMET webalkalmazás fejlesztés. Tóth Ádám Jasmin Media Group

Hálózati alapismeretek

A függvény kód szekvenciáját kapcsos zárójelek közt definiáljuk, a { } -ek közti részt a Bash héj kód blokknak (code block) nevezi.

Hálózati architektúrák és Protokollok GI 8. Kocsis Gergely

Az Internet működésének alapjai


Hálózati réteg. Feladata: a csomag eljusson a célig Több útválasztó Ez a legalacsonyabb rétek, mely a két végpont

UDP idő szerver. UDP protokollal kapcsolatos ismeretek elmélyítése. Egy UPP protokollt használó időszerver megvalósítása

Dr. Varga Imre. Socket-programozás. C nyelven

Számítógépes hálózatok

Adatbiztonság PPZH május 20.

[SZÁMÍTÓGÉP-HÁLÓZATOK]

Számítógép hálózatok gyakorlat

Tűzfalak működése és összehasonlításuk

Távközlési informatika II.

C programozási nyelv Pointerek, tömbök, pointer aritmetika

Megoldás. Feladat 1. Statikus teszt Specifikáció felülvizsgálat

Számítógépes hálózatok I.

int azt az elõzõ részbõl megtudtuk, a rétegeknek az a feladatuk, hogy valamiféle feladatot végezzenek

Számítógépes Hálózatok GY 3-4.hét

Számítógépes Hálózatok. 7. gyakorlat

I. Házi Feladat. internet. Határidő: V. 30.

7. fejezet: Mutatók és tömbök

Hálózatok. Alapismeretek. A hálózatok célja, építőelemei, alapfogalmak

Számítógépes Hálózatok GY 4.hét

Tartalom. Router és routing. A 2. réteg és a 3. réteg működése. Forgalomirányító (router) A forgalomirányító összetevői

MOBILTELEFONON keresztüli internet telefonálás

Kommunikáció. Folyamatok közötti kommunikáció. Minden elosztott rendszer alapja

Socket programozás Példák

Tisztelt Telepítő! A központ és az alkalmazás összehangolását a következőképpen hajthatja végre:

PTE-PROXY VPN használata, könyvtári adatbázisok elérhetősége távolról

Tájékoztató. Használható segédeszköz: -

A 35/2016. (VIII. 31.) NFM rendelet szakmai és vizsgakövetelménye alapján.

OSI-ISO modell. Az OSI rétegek feladatai: Adatkapcsolati réteg (data link layer) Hálózati réteg (network layer)

Hálózatos adatbázis-kapcsolódási problémák és azok javítása

Számítógépes Hálózatok. 3. gyakorlat

Advanced PT activity: Fejlesztési feladatok

A számítógép-hálózat egy olyan speciális rendszer, amely a számítógépek egymás közötti kommunikációját biztosítja.

1. Egyszerű (primitív) típusok. 2. Referencia típusok

Beállítások 1. Töltse be a Planet_NET.pkt állományt a szimulációs programba! A teszthálózat már tartalmazza a vállalat

SSL elemei. Az SSL illeszkedése az internet protokoll-architektúrájába

TCP szerver. TCP szerver alkalmazás írásának az elsajátítása TCP protokoll tulajdonságainak a tanulmányozása kisérleti úton

Adatkapcsolati réteg 1

Oralce kliens installálása Windows Server 2003-ra

A WebEye Comlink v (84) és a WebEye Connect v (84) kapcsolata Rövid felhasználói útmutató

Folyamatok. 6. előadás

Windows rendszeradminisztráció és Microsoft szerveralkalmazások támogatása. 3. óra. Kocsis Gergely, Kelenföldi Szilárd

vbar (Vemsoft banki BAR rendszer)

SZÁMÍTÓGÉP HÁLÓZATOK BEADANDÓ ESSZÉ. A Windows névfeloldási szolgáltatásai

Adatátviteli rendszerek Mobil IP. Dr. habil Wührl Tibor Óbudai Egyetem, KVK Híradástechnika Intézet

Az operációs rendszer szerkezete, szolgáltatásai

Internet Protokoll 4 verzió

Számítógépes Hálózatok. 5. gyakorlat

A számítógép-hálózatok tervezését struktúrális módszerrel végzik, azaz a hálózat egyes részeit réteg-ekbe (layer) vagy más néven szint-ekbe (level)

A TCP/IP modell szállítási rétege

URL-LEL ADOTT OBJEKTUM LETÖLTÉSE (1) URL-LEL ADOTT OBJEKTUM LETÖLTÉSE

Hálózati architektúrák laborgyakorlat

Számítógépes Hálózatok. 4. gyakorlat

Bérprogram vásárlásakor az Ügyfélnek ben és levélben is megküldjük a termék letöltéséhez és aktiválásához szükséges termékszámot.

SEGÉDLET. A TTMER102 - FPGA-alapú hálózati eszközfejlesztés című méréshez

IP alapú távközlés. Virtuális magánhálózatok (VPN)

BEÁGYAZOTT RENDSZEREK TERVEZÉSE UDP csomag küldése és fogadása beágyazott rendszerrel példa

Programozás C++ -ban 2007/7

Hálózati architektúrák laborgyakorlat

Hálózati architektúrák laborgyakorlat

Technikai tudnivalók a Saxo Trader Letöltéséhez tűzfalon vagy proxy szerveren keresztül

IBM WebSphere Adapters 7. változat 5. alváltozat. IBM WebSphere Adapter for felhasználói kézikönyv 7. változat 5.kiadás

Az internet az egész világot behálózó számítógép-hálózat.

Alapfogalmak. Biztonság. Biztonsági támadások Biztonsági célok

G Data MasterAdmin 9 0 _ 09 _ _ # r_ e p a P ch e T 1

C++ referencia. Izsó Tamás február 17. A C++ nyelvben nagyon sok félreértés van a referenciával kapcsolatban. A Legyakoribb hibák:

Alhálózatok. Bevezetés. IP protokoll. IP címek. IP címre egy gyakorlati példa. Rétegek kommunikáció a hálózatban

Tartalom. Hálózati kapcsolatok felépítése és tesztelése. Rétegek használata az adatok továbbításának leírására. OSI modell. Az OSI modell rétegei

TRBOnet Térinformatikai terminál és diszpécseri konzol

Hálózati ismeretek. Az együttműködés szükségessége:

Számítógép labor V. Egyszer Web szerver. Dokumentáció. Készítette: Ács Gergely (K4C03M)

Hálózatok I. A tárgy célkitűzése

Dr. Wührl Tibor Ph.D. MsC 04 Ea. IP P címzés

Léteznek nagyon jó integrált szoftver termékek a feladatra. Ezek többnyire drágák, és az üzemeltetésük sem túl egyszerű.

Átírás:

6. A szállítási réteg A szállítási réteg nem csak a hétrétegű architektúra egy újabb rétege, hanem az egész protokollhierarchia legfontosabb rétege. Feladata az, hogy megbízható, gazdaságos adatszállítást biztosítson a forráshoszttól a célhosztig, függetlenül magától a fizikai hálózattól vagy az aktuálisan használt kommunikációs alhálózatoktól. A szállítási réteg nélkül a rétegezett protokollkoncepciónak nem sok értelme lenne. Ebben a fejezetben a szállítási réteget fogjuk részletesen tanulmányozni, beleértve annak szolgálatait, tervezését, protokolljait és teljesítőképességét. 6.1. A szállítási szolgálat A következő néhány alfejezet a szállítási szolgálat alapjait mutatja be. Áttekintjük, hogy milyen szolgálatokat kínál az alkalmazási réteg (vagy ha egyáltalán van, a viszony réteg) felé, különös tekintettel a szolgáltatás minőségének jellemzésére. Végül megvizsgáljuk, hogy az alkalmazások hogyan érik el a szállítási szolgálatokat, azaz milyen interfész áll rendelkezésükre. 6.1.1. A felső rétegeknek nyújtott szolgálatok A szállítási réteg legfőbb célja az, hogy hatékony, megbízható és gazdaságos szolgálatot nyújtson felhasználóinak, általában az alkalmazási rétegben futó folyamatoknak. E cél érdekében a szállítási réteg felhasználja a hálózati réteg által nyújtott szolgálatokat. A szállítási rétegen belül azt a hardver és/vagy szoftver elemet, amely a munkát végzi, szállítási funkcionális elemnek vagy szállítási entitásnak (transport entity) nevezzük. Ez lehet az operációs rendszer magjának (kernelének) része, önálló felhasználói folyamat, egy hálózati alkalmazáshoz tartozó könyvtár vagy a hálózati illesztő kártya. A hálózati, szállítási és alkalmazási réteg kapcsolatát a 6.1. ábra szemlélteti. Ahogy a hálózati szolgálatoknak két típusa van, összeköttetés alapú és összeköttetés nélküli, ugyanígy kétféle szállítási szolgálat létezik. Az összeköttetés alapú szállítási szolgálat sok tekintetben hasonló az összeköttetés alapú hálózati szolgálathoz. Mind-

A SZÁLLÍTÁSI RÉTEG 527 1. hoszt Alkalmazási (vagy viszony) réteg Szállítási cím / Alkalmazásiszállítási interfész 2. hoszt Alkalmazási (vagy viszony) réteg Szállítási entitás Hálózati cím Hálózati réteg V TPDU D- Szállítási protokoll Szállításihálózati interfész Szállítási entitás Hálózati réteg 6.1. ábra. A hálózati, szállítási és alkalmazási réteg két esetben az összeköttetésnek három fázisa van: létesítés, adatátvitel és lebontás. A címzés és forgalomszabályozás szintén hasonló a két rétegben. Az összeköttetés nélküli szállítási szolgálat is nagyon hasonló az összeköttetés nélküli hálózati szolgálathoz. A nyilvánvaló kérdés ezután az, hogy ha a szállítási réteg szolgálata ennyire hasonló a hálózati réteg szolgálatához, akkor miért van mégis két külön réteg. Miért nem elegendő egy? A válasz egy apró, de lényeges különbségben rejlik, amelyhez az 1.9. ábrára kell visszautalnunk. A szállítási réteg kódja teljes egészében a felhasználók gépein fut, szemben a hálózati réteggel, ami nagyrészt a routereken, a routereket pedig a szolgáltató üzemelteti (legalábbis a nagy kiterjedésű hálózatokban). Mi történik, ha a hálózati réteg nem nyújt megfelelő szolgáltatásminőséget? Esetleg gyakran veszti el a csomagokat? Mi történik, ha a routerek időről időre lefagynak? Ezekben az esetekben bizony bajok történnek. A felhasználóknak nincs igazi beleszólása a hálózati réteg működésébe, ezért nem tudják azzal megoldani a gyenge minőségű szolgálat problémáját, hogy több routert vagy jobb hibakezelést építenek be a hálózati rétegbe. Az egyetlen lehetőség az, hogy egy olyan másik réteget építsünk rá a hálózati rétegre, amely javítja a szolgáltatásminőséget. Ha egy összeköttetés alapú alhálózatban a szállítási entitás egy hosszú átvitel közepén arról értesül, hogy hálózati öszszeköttetése hirtelen megszakadt, akkor sehogyan sem tudja meghatározni, hogy mi történt az éppen úton levő csomagokkal. Ezért új hálózati összeköttetést kell kiépítenie, amelyen azután egy lekérdezéssel megkérdezheti a társentitástól, hogy mely adatok érkeztek meg és melyek nem. Ezután az átvitelt ott folytathatják, ahol az félbemaradt. A szállítási réteg létezése lényegében azt teszi lehetővé, hogy a szállítási szolgálat megbízhatóbb lehessen annál a hálózati szolgálatnál, amelyre ráépül. A szállítási réteg képes felfedezni és kiegyenlíteni az elveszett csomagok és a csonkolt adatok okozta hibákat. Mindezen felül a szállítási szolgálat primitívjei könyvtári függvényhívásokként is megvalósíthatók, és ezzel függetleníthetó'k a hálózati szolgálat primitívjeitől. A hálózati szolgálat hívásai az egyes hálózatokban jelentősen eltérhetnek (egy össze-

528 SZÁMÍTÓGÉP-HÁLÓZATOK köttetés nélküli LAN-szolgálat például jelentősen különbözhet egy összeköttetés alapú WAN-szolgálattól). A hálózati szolgálat részletei rejtve maradnak a szállítási szolgálat primitívjei mögött. A hálózati szolgálat lecserélésekor így mindössze arra van szükség, hogy a könyvtári függvények egyik készletét lecseréljük egy másikra, amely egy másik szolgálatra ráépülve látja el ugyanazt a feladatot. A szállítási rétegnek köszönhetően az alkalmazások programozói egy szabványos primitívkészletre írhatják a kódot, és az így megírt programok a hálózatok széles skáláján működnek. Mindezt anélkül, hogy a programozóknak a különféle alhálózati interfészekkel és a megbízhatatlan átvitellel törődniük kellene. Ha minden létező hálózat tökéletes lenne, és mindegyik egy olyan közös szolgálatprimitív-készletet használna, amely garantáltan soha de soha nem változik, akkor lehet, hogy nem lenne szükség a szállítási rétegre. A gyakorlati életben azonban azt a kulcsfontosságú feladatot teljesíti, hogy elszigeteli a magasabb rétegeket a műszaki megoldásoktól és az alhálózat tökéletlenségeitől. A fenti ok miatt sokan megkülönböztetik az 1-4. rétegeket a 4. feletti réteg(ek)től. Az alsó négy réteget tekinthetjük a szállítási szolgáltatónak (transport service provider), míg a magasabb réteg(ek)et tekinthetjük a szállítási szolgálat felhasználójának (transport service user). A szolgáltató és a felhasználó ezen elkülönítése jelentős hatással van a rétegek kialakítására, és kulcsfontosságú helyzetbe hozza a szállítási réteget, mivel ez alkotja a fő határvonalat a szolgáltató és a megbízható adatátviteli szolgálat felhasználója között. 6.1.2. Szállítási szolgálati primitívek A szállítási rétegnek néhány műveletet, vagyis egy szállítási szolgálati interfészt kell biztosítania az alkalmazási programok számára annak érdekében, hogy a felhasználók hozzáférhessenek a szolgálataihoz. Minden szállítási szolgálat egyedi interfésszel rendelkezik. Ebben a szakaszban először egy egyszerű (hipotetikus) szállítási szolgálatot és annak interfészét fogjuk megvizsgálni, hogy bemutassuk a legalapvetőbb jellegzetességeket. A következő szakaszban pedig egy gyakorlati példával ismerkedünk majd meg. A szállítási szolgálat hasonlít a hálózati szolgálathoz, azonban van néhány fontos eltérés. A fő különbség köztük az, hogy a hálózati szolgálat a valódi hálózatok által nyújtott szolgáltatásokat igyekszik modellezni azok gyengéivel együtt. Az igazi hálózatok csomagokat veszíthetnek, tehát a hálózati szolgálat általában nem megbízható. Ezzel szemben az (összeköttetés alapú) szállítási szolgálat megbízható. Természetesen a valódi hálózatok nem hibamentesek, de pontosan a szállítási réteg feladata az, hogy egy nem megbízható hálózatra épülve megbízható szolgálatot nyújtson. Vegyünk például két olyan folyamatot, amelyek a UNIX-ban csövekkel vannak összekötve. Ezek azt feltételezik, hogy a köztük levő összeköttetés tökéletes. Hallani sem akarnak nyugtázásokról, elvesztett csomagokról, torlódásról vagy más, ehhez hasonló problémáról. Egy 100 százalékosan megbízható összeköttetést akarnak használni. Az A folyamat beteszi az adatokat a cső egyik végén, a B folyamat kiveszi a másik végén. Ez a lényege a szállítási szolgálatnak: elrejteni a hálózati szolgálat hiányosságait, hogy az alkalmazási folyamatok hibamentes bitfolyamot feltételezhessenek.

A SZÁLLÍTÁSI RÉTEG 529 Primitív Elküldött TPDU Jelentés LISTEN (nincs) Vár, amíg egy folyamat kapcsolódni nem próbál CONNECT CONNECTION REQ. Összeköttetést próbál létrehozni SEND DATA Adatot küld RECEIVE (nincs) Vár, amíg adat (DATA TPDU) nem érkezik DISCONNECT DISCONNECTION REQ. Ez az oldal bontani kívánja az összeköttetést 6.2. ábra. Egy egyszerű szállítási szolgálat primitívjei A szállítási réteg járulékos tulajdonsága, hogy megbízhatatlan (datagram) szolgálatot is tud nyújtani. Erről azonban viszonylag keveset lehet mondani, így a figyelmünket ebben a fejezetben főként az összeköttetés alapú szállítási szolgálatokra fogjuk irányítani. Ennek ellenére van néhány olyan alkalmazás (mint például a kliens-szerver-alkalmazások és a közvetítéses multimédia-szolgáltatás) amelyekhez előnyös az öszszeköttetés nélküli szállítás, ezért egy keveset még fogunk beszélni erről a későbbiekben. Egy másik különbség a hálózati és a szállítási szolgálat között a szolgálat felhasználóinak köre. A hálózati szolgálatot csak a szállítási entitások használják. Kevesen írják meg a saját szállítási entitásaikat, ezért kevés program látja a csupasz hálózati szolgálatot. Ezzel ellentétben viszont sok alkalmazás (ezzel együtt programozó) használja a szállítási primitíveket, ezért a szállítási szolgálatnak kényelmesnek és könnyen használhatónak kell lennie. A 6.2. ábrán bemutatunk öt lehetséges szállítási primitívet. Ez a szállítási szolgálat csak egy puszta váz, de ízelítőt ad egy összeköttetés alapú szállítási interfész lényeges feladataiból. Lehetővé teszi a felhasználói programoknak összeköttetések létesítését, használatát és lebontását, ami a legtöbb alkalmazásnak elegendő is. Hogy a primitívek működésére is lássunk példát, vegyünk egy alkalmazást egy szerverrel és több távoli klienssel. Először a szerver egy LISTEN (FIGYELÉS) primitívet hajt végre, tipikusan egy könyvtári függvényhívással, ami rendszerhívást eredményez, hogy a szerver egy kliens jelentkezéséig blokkolódjon. Amikor egy kliens beszélni akar a szerverrel, egy CONNECT (KAPCSOLÁS) primitívet hajt végre. A szállítási entitás ezt úgy valósítja meg, hogy a hívót blokkolja, és egy csomag adatmezejébe ágyazott szállítási üzenetet küld a szerver szállítási entitása részére. Itt rövid terminológiai kitérőt kell tennünk. Jobb híján az esetlen TPDU (Transport Protocol Data Unit - szállítási protokoll adategység) elnevezést kényszerülünk használni szállítási entitások közötti üzenetekre. Ezek a TPDU-k (melyeket a szállítási réteg küld és fogad) csomagokba (amiket a hálózati réteg használ) vannak beágyazva. A csomagok viszont (adatkapcsolati réteg által kezelt) keretekben (frame) foglalnak helyet. Amikor egy keret megérkezik, az adatkapcsolati réteg földolgozza a keret fejrészét, és a keret adatmezejének tartalmát továbbadja a hálózati entitásnak. A hálózati entitás földolgozza a csomag fejrészét, és az adatmező tartalmát átadja a szállítási entitásnak. Ezt a beágyazott struktúrát szemlélteti a 6.3. ábra.

530 SZÁMÍTÓGÉP-HÁLÓZATOK Keretfejrész Csomagfejrész TPDU fejrész 4- ~zi TPDU adatmező Csomag adatmező Keret adatmező 6.3. ábra. A TPDU-k, csomagok és keretek beágyazása Visszatérve a kliens-szerver példához, a kliens CONNECT hívása hatására a szállítási entitás CONNECTION REQUEST (ÖSSZEKÖTTETÉS-KÉRÉS) TPDU-t küld a szerver felé. Amikor az megérkezik, a szállítási entitás meggyőződik arról, hogy a szerver LISTEN hívásban várakozik (azaz kész kéréseket kiszolgálni). Ekkor megszünteti a szerver blokkolását, és CONNECTION ACCEPTED (összekötetés kérés elfogadva) TPDU-t küld vissza a kliensnek. Amint a TPDU megérkezik, a kliens blokkolása is feloldódik, így az összeköttetés létrejön. Ekkor megkezdődhet az adatátvitel a SEND és RECEIVE (ADÁS és VÉTEL) primitívek segítségével. A legegyszerűbb esetben bármelyik fél végrehajthat egy (blokkoló) RECEIVE hívást, hogy várakozzon a partner által (SEND primitívvel) küldött adatra. Amikor a TPDU megérkezik, a fogadó blokkolása megszűnik, földolgozza a kapott adatot, és választ küld. Amíg mindkét fél nyomon tudja követni, hogy ki mikor következik, ez a rendszer jól működik. Megjegyezzük, hogy a hálózati rétegben még egy egyszerű egyirányú adatforgalom is jóval bonyolultabb, mint a szállítási rétegben. Minden adatcsomagot nyugtáznak, sőt a vezérlő TPDU-kat hordozó csomagokra is érkezik közvetett vagy közvetlen nyugtázás. Ezeket a nyugtázásokat a szállítási entitások kezelik a hálózati rétegbeli protokollok segítségével, és a szállítási felhasználók számára ezek nem láthatók. Hasonlóan, a szállítási entitásoknak kell foglalkozniuk az időzítésekkel és az ismétlésekkel. Ezen mechanizmusokból szintén semmit sem látnak a szállítási felhasználók. Számukra az összeköttetés egy megbízható csővezeték, azaz: amit egy felhasználó a cső egyik végén betölt, az a másik végén változatlanul megjelenik. A bonyolultság elrejtésének képessége miatt a rétegezett protokollok nagyon hatékony eszköznek bizonyulnak. Amikor egy összeköttetésre többé nincs szükség, azt le kell bontani, hogy ne foglaljon fölöslegesen táblahelyet a két szállítási entitáson belül. A bontásnak két változata van: aszimmetrikus és szimmetrikus. Az aszimmetrikus esetben valamelyik szállítási felhasználó kiad egy DISCONNECT primitívet, aminek hatására a szállítási entitás egy DISCONNECT (ÖSSZEKÖTTETÉS-BONTÁS) TPDU-t küld a távoli szállítási entitásnak. A TPDU megérkezésekor az összeköttetés lebomlik. A szimmetrikus esetben mindkét irányt külön, a másiktól függetlenül zárják le. Amikor az egyik fél DISCONNECT hívást kezdeményez, az azt jelenti, hogy nincs több elküldenivaló adata, de továbbra is hajlandó partnere adatait fogadni. Ebben a modellben az összekötetés akkor ér véget, amikor mindkét fél végrehajtotta a DISCONNECT primitívet.

A SZÁLLÍTÁSI RÉTEG 531 Összeköttetés kérés TPDU érkezett TÉTLEN Az összeköttetéslétesítés primitív végrehajtva PASSZÍV LÉTESÍTÉS FOLYAMATBAN AKTÍV LÉTESÍTÉS FOLYAMATBAN _ ÖSSZEKÖTTETÉS Az összeköttetés-létesítés LÉTREJÖTT Összeköttetés elfogadva primitív végrehajtva TPDU érkezett Összeköttetés-bontás Az összeköttetés bontása kérés TPDU érkezett primitív végrehajtva PASSZÍV BONTÁS h-- FOLYAMATBAN AKTÍV BONTÁS FOLYAMATBAN Az összeköttetés-bontás primitív végrehajtva TÉTLEN Összeköttetés-bontás kérése TPDU érkezett 6.4. ábra. Egyszerű összeköttetés-kezelés állapotdiagramja. A dőlt betűvel szedett állapotátmeneteket beérkező csomagok váltják ki. A folytonos nyilak a kliens, a szaggatott nyilak a szerver állapotátmeneteit mutatják Ezen egyszerű primitíveken alapuló összeköttetés-létesítés és -bontás állapotdiagramja látható a 6.4. ábrán. Minden állapotátmenetet valamilyen esemény vált ki: vagy egy, a helyi felhasználó által végrehajtott primitív, vagy egy beérkező csomag. Az egyszerűség kedvéért föltételezzük, hogy minden TPDU nyugtázása külön történik. Feltesszük továbbá, hogy szimmetrikus összeköttetés-bontást modellezünk úgy, hogy a kliens kezdeményez. Megjegyzendő, hogy az ábra meglehetősen elnagyolt. Később megvizsgálunk egy ennél valósághűbb modellt is. 6.1.3. Berkeley TCP-primitívek Vizsgáljunk meg röviden egy másik szállítási primitívkészletet, a Berkeley UNIX-ban használt TCP-socket primitíveket. Ezeket a 6.5. ábrán is felsorolt primitíveket széleskörűen alkalmazzák az Internet programozásában. Nagyvonalakban követik az első példában bemutatott modellt, de több lehetőséget és rugalmasságot nyújtanak. Itt nem térünk ki a megfelelő TPDU-kra, annak tárgyalására a TCP tanulmányozása után kerül sor e fejezet későbbi részében. Az első négy primitívet az ábrán látható sorrendben hajtja végre a szerver. A

532 SZÁMÍTÓGÉP-HÁLÓZATOK Primitív SOCKET BIND LISTEN ACCEPT CONNECT SEND RECEIVE CLOSE Jelentés Uj kommunikációs végpont (csatlakozó) létrehozása Helyi cím hozzárendelése a csatlakozóhoz Összeköttetés-elfogadási szándék bejelentése, várakozási sor hosszának megadása Hívó blokkolása összeköttetés-létesítési kísérletig Próbálkozás összeköttetés-létesítésre Adatküldés az összeköttetésen keresztül Adatfogadás az összeköttetésről Összeköttetés bontása 6.5. ábra. TCP-socket primitívek SOCKET primitív új végpontot (csatlakozót) hoz létre, és táblahelyet foglal le a szállítási entitásban. A hívás paraméterei rögzítik a használni kívánt címzési formát, a szolgálat típusát (pl. megbízható bitfolyam) és a protokollt. A sikeres SOCKET hívás közönséges állományleíróval tér vissza, amit a további hívások használnak éppúgy, mint az OPEN rendszerhívásnál. Az újonnan létrehozott csatlakozóknak (socket) nincs címük, a hozzárendelést a BIND primitív végzi. Amint a szerver címet rendelt a végponthoz, távoli kliensek csatlakozhatnak hozzá. Annak oka, hogy a cím megadása nem a SOCKET hívással történik az, hogy vannak olyan folyamatok, amelyek számára fontosak a címek (pl. évek óta ugyanazt a címet használják, és ez a cím mindenki által ismert), míg mások számára a cím megválasztása közömbös. Ezt követi a LISTEN hívás, amely a beérkező hívások várakozási sorának foglal helyet arra az esetre, amikor a szerverhez egy időben több kliens is kapcsolódni kíván. Ellentétben az első példában használt LlSTEN-nel, a TCP-modellben a LISTEN nem blokkoló hívás. A szerver ACCEPT primitívet hajt végre ahhoz, hogy blokkolja magát egy bejövő összeköttetés-kérésig. Amikor egy összeköttetést kérő TPDU érkezik, a transzportentitás az eredetivel azonos tulajdonságokkal rendelkező új végpontot hoz létre, és hozzárendel egy állományleírót. A szerver ekkor új folyamatot vagy szálat indít az új végponton létrejövő kapcsolat kezelésére, és tovább várja a következő kérést az eredeti végponton. Az ACCEPT egy szokványos állományleírót ad vissza, amelyet ezután a megszokott módon lehet írásra és olvasásra használni ugyanúgy, mint a tényleges állományok leíróit. Most vegyük szemügyre a kliensoldalt. Itt ugyancsak egy végpontot kell először létrehozni a SOCKET primitív segítségével, de BIND hívás nem szükséges, mivel a használt cím nem érdekli a szervert. A CONNECT primitív blokkolja a hívót, és belekezd az összeköttetés-létesítési folyamatba. Amikor ezt befejezi (azaz a megfelelő TPDU megérkezett a szervertől), a kliensfolyamat blokkolása megszűnik, és az összeköttetés létrejön. Ekkor mindkét fél a SEND és RECEIVE primitív segítségével küldhet és fogad-

A SZÁLLÍTÁSI RÉTEG 533 hat adatokat a duplex összeköttetésen keresztül. Amennyiben a SEND és a RÉCÉIVÉ különleges lehetőségeire nincsen szükség, a UNIX szabványos REÁD és WRITE rendszerhívásait is lehet használni. Az összeköttetés bontása szimmetrikus. Amikor mindkét fél végrehajtotta a CLOSE primitívet, az összeköttetés megszűnik. 6.1.4. Csatlakozó-programozási példa: egy internetes állományszerver A csatlakozók (socket) hívásainak használatát a 6.6. ábrán megadott kliens és szerver kódján keresztül mutatjuk be. Az ábrán egy nagyon egyszerű internetes állományszerver látható, valamint egy példa-kliens, amely ezt a szervert használja. A kódnak számos hiányossága van (ezeket meg fogjuk tárgyalni), de elméletileg a szerver kódját bármely internetre kötött UNIX rendszeren le lehet fordítani és le is lehet futtatni. Ezután a kliens kódja is lefordítható és futtatható a világ bármely másik UNIX-os gépén. A kliens kódja a megfelelő' paraméterekkel indítva bármely olyan állományt le tud tölteni a szerverről, amelyhez annak a saját gépén hozzáférése van. Az állományt a kliens a standard outputra teszi, amelyet természetesen tovább irányíthatunk egy állományba vagy egy csővezetékbe. Elsőként vizsgáljuk meg a szerver kódját! Az eleje néhány szabványos könyvtárillesztést tartalmaz, amelyek közül az utolsó három tartalmazza a legfőbb Internettel kapcsolatos definíciókat és adatszerkezeteket. Ezután a SERVER_PORT definíciója következik. Az 12345-ös portot jelöltük ki erre a célra, de ez a szám tetszőleges. Bármely olyan 1024 és 65535 közötti portszám ugyanilyen alkalmas erre a célra, amelyet más folyamat nem használ. Természetesen a kliensnek és a szervernek azonos portot kell használnia. Amennyiben ez a szerver a jövőben világsikerré válik (ami elég valószínűtlen, figyelembe véve, hogy mennyire primitív), egy állandó, 1024 alatti portot jelölnek majd ki neki, és meg fog jelenni a www.iana.org-on is. A szervei következő két sora két szükséges állandót definiál. Az első az állományátvitel során használt adatblokkok méretét határozza meg. A második azt adja meg, hogy hány kapcsolat várakozhat egyszerre a portra, mielőtt a szerver eldobná a további beérkező kéréseket. A lokális változók deklarációja után kezdődik a szerver tényleges kódja. A program a szerver IP-címét tartalmazó adatszerkezetek inicializálásával indul. Ezt az adatszerkezetet hamarosan a szerver csatlakozójához kötjük majd. A memset meghívása az egész adatszerkezetet 0-ba állítja, a következő három hozzárendelés pedig kitölti három mezőjét. Ezek közül a legutolsó tartalmazza a szerver portját. A htonl és a htons függvények használata azért szükséges, mert az értékeket egy szabványos formára kell alakítanunk annak érdekében, hogy a kód mind a nagy-endián (pl. SPARC), mind a kis-endián (pl. a Pentium) számábrázolást használó processzorokon helyesen fusson. A pontos szemantikájuk itt most nem érdekes. A szerver ezután létrehoz egy csatlakozót és (az Í < 0 feltétellel) ellenőrzi, hogy ez rendben lezajlott-e. A kód termékként kiadott változatában egy hangyányit bőbeszédűbb hibaüzenetet kellene írni. A setsockopt meghívására azért van szükség, hogy a szerver újrahasználhassa a portot, és így határozatlan ideig futhasson és szolgálhassa ki a beérkező kéréseket. Az IP-címet mostanra hozzákötöttük a csatlakozóhoz, és azt

534 SZÁMÍTÓGÉP-HÁLÓZATOK is megvizsgáltuk, hogy a bind hívása sikeres volt-e. Az inicializálás végsó' lépése a listen meghívása, amellyel a szerver bejelenti, hogy hajlandó a bejövó' hívások elfogadására, valamint megbízza a rendszert, hogy QUEUE_SIZE-nyi kérést várakoztasson abban az esetben, ha akkor érkezik új kérés, amikor a szerver éppen egy másik kérés kiszolgálásán dolgozik. Ha a várakozási sor megtelik, és további kérések érkeznek, akkor azokat a rendszer csendben eldobja. Ez az a pillanat, amikor a szerver belép a fő ciklusba, amelyet ezután már el sem hagy. Leállításának egyetlen módja az, ha kívülről lövik ki. Az accept meghívása addig blokkolja a szervert, amíg összeköttetési kérés nem érkezik egy klienstől. Ha az accept hívása sikeres, akkor egy állományleíróval tér vissza, amelyet ezután ahhoz hasonlóan lehet írásra és olvasásra használni, ahogyan egy csővezeték állomány leírójával lehet a csővezetéket írni és olvasni. Az egyirányú csővezetékekkel ellentétben azonban a csatlakozók kétirányúak, így az sa-t (socket address; a csatlakozó címe) egyaránt lehet használni az összeköttetésről való olvasáshoz, illetve az arra történő íráshoz. Miután a szerver kiépítette az összeköttetést, kiolvassa az sa-bó\ a kért állomány nevét. Ha a név nem áll azonnal rendelkezésre, akkor addig várakozik, amíg meg nem kapja. Miután a szerver megkapta az állomány nevét, megnyitja az állományt és belép abba a hurokba, amely addig olvassa ki sorban az állomány darabjait és írja ki ezeket a csatlakozóra, amíg a teljes állományt át nem másolta. Ezután a szerver lezárja az állományt és az összeköttetést, majd várni kezd a következő kapcsolódási kérésre. Ezt a hurkot örökké ismétli. Most vizsgáljuk meg a kliens kódját. A működésének megértéséhez elengedhetetlen megérteni azt, hogy hogyan kell indítani. Ha feltesszük, hogy a program neve client, akkor egy tipikus hívása a következő: client flits.cs.vu.nl /usr/tom/allomanynev >f Ez a hívás csak abban az esetben sikeres, ha a szerver már fut a.flits.cs.vu.nl-en, a /usr/tom/allomanynev nevű állomány létezik, és a szervernek olvasási joga is van rá. Ha a hívás sikeres, akkor a kliensprogram az interneten keresztül megkapja az állományt és kiírja/-be, majd ezután kilép. Mivel a szerver egy-egy átvitel után tovább fut, a klienst újra és újra elindíthatjuk, ha más állományokat is meg akarunk szerezni. A kliens kódja néhány függvénykönyvtár betöltésével és néhány deklarációval kezdődik. Az első dolga ellenőrizni azt, hogy megfelelő számú paraméterrel indították-e a programot (az argc = 3a program nevén kívül még 2 paramétert jelent). Figyeljük meg, hogy az argvfl] a szerver nevét tartalmazza (a példában flits.cs.vu.nl), és ezt a gethostbyname használatával alakítjuk IP-címmé. Ez a függvény a DNS szolgálatot használja a cím kikeresésére. A DNS-t a 7. fejezetben fogjuk tanulmányozni. Ezután a kliens egy csatlakozót (socket) hoz létre és inicializálja azt, majd a connect hívással megpróbál létrehozni egy TCP-összeköttetést a szerver felé. Ha a megnevezett gépen fut a szerver, továbbá figyeli a SERVER_PORT-ot, és vagy tétlen, vagy van szabad helye a listen hívás várakozási sorában, akkor az összeköttetés (előbb vagy utóbb) kiépül. A kliens ekkor a csatlakozóra történő írással elküldi az állomány nevét az összeköttetésen keresztül. Az elküldött bájtok száma eggyel nagyobb a név tényleges hosszánál, mivel a nevet lezáró 0 bájtot is el kell küldeni a szervernek, hogy az tudja, hol van vége a névnek.

A SZÁLLÍTÁSI RÉTEG 535 Ekkor a kliens egy olyan hurokba lép, amelyben az állományt blokkonként kiolvassa a csatlakozóról, és rámásolja a blokkokat a standard outputra. Amikor ezzel végzett, egyszerűen kilép. /*Ezen az oldalon egy olyan kliensprogram található, amely a következő oldalon látható szerverprogramtól le tud kérni egy állományt. A szerver a teljes állomány átküldésével válaszol. 7 #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define SERVER_PORT 12345 /* tetszőleges, de a két oldalon azonosnak kell lennie */ #define BUF^SIZE 4096 /* átvitt darabok mérete */ int main(int argc, char *argv) { int c, s, bytes; char buf[buf_size]; /* puffer az érkező állománynak */ struct hostent *h; /* info a szerverről 7 struct sockaddrjn channel; /* ez tárolja majd az IP-címet 7 if (argc!=3) fatalflndítás: client <szervemév> <állománynév>"); h = gethostbyname(argv[1]); /* lekérjük a hoszt IP-címét 7 if (!h) fatalfgethostbyname sikertelen"); s = socket(pf_inet, SOCK_STREAM, IPPROTO_TCP); if (s <0) fatal("csatlakozó"); memset(&channel, 0, sizeof(channel)); channel.sin_family= AFJNET; memcpy(&channel.sin_addr.s.addr, h->h_addr, h->h_length); channel.sin port=htons(server_port); c = connect(s, (struct sockaddr *) &channel, sizeof(channel)); if (c <0) fatal("az összeköttetés kiépítése sikertelen"); /* Az összeköttetés létrejött. Elküldjük az állomány nevét, 0-val lezárva. 7 write(s, argv[2], strlen(argv[2])+1) /* Kiolvassuk az állományt a csatlakozóról és kiírjuk a strandard outputra. 7 while(1){ bytes = read(s, buf, BUF SIZE) /* olvasás a csatlakozóról 7 if (bytes <= 0) exit(0); /* vége van az állománynak? 7 write(1, buf, bytes); /* írás a standard outputra 7 } } fatal(char *string) { printf("%s\n", string); exit(1); } 6.6. ábra. A csatlakozókat használó kliens kódja. A szerver kódja a következő oldalon találh J

536 SZÁMÍTÓGÉP-HÁLÓZATOK #include <sys/types.h> /* Ez a szerver kódja */ #include <sys/fcntl.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define SERVER_PORT 12345 /* tetszőleges, de a két oldalon azonosnak kell lennie */ #define BUF_SIZE 4096 /* átvitt darabok mérete */ #definequeue_size10 int main(int argc, char *argv[]) { int s, b, I, fd, sa, bytes, on = 1; char buf[buf_size]; /* puffer a kimenő állománynak 7 struct sockaddrjn channel; /* ez tárolja majd az IP-címet 7 /* Felépítjük a csatlakozóhoz szükséges adatszerkezetet. */ memset(&channel, 0, sizeof(channel)); /* nullázzuk a csatornát */ channel.sin_family = AFJNET; channel. sin_addr.s_addr = htonl(inaddr_any); channel.sin_port = htons(server_port); /* Passzív megnyitás. Összeköttetésre várunk. */ s = socketíafjnet, SOCK_STREAM, IPPROTO_TCP); /* csatlakozó létrehozása 7 if (s < 0) fatal("socket sikertelen"); setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)); b = bind(s, (struct sockaddr *) Schannel, sizeof(channel)); if (b < 0) fatal("bind sikertelen"); I = listen(s, QUEUE_SIZE); /* megadjuk a várakozási sor hosszát */ if (I < 0) fatalflisten sikertelen"); /* A csatlakozó kész és be van kötve. Várjuk az összeköttetéseket, és feldolgozzuk azokat. */ while(1){ sa = accept(s, 0, 0); /* várakozás egy összeköttetési kérésre */ if (sa < 0) fatal("accept sikertelen"); } } read(sa, buf, BUF_SIZE); /* beolvassuk az állománynevet a csatlakozóról */ /* Megszerezzük és átvisszük az állományt.*/ fd = open(buf, 0_RDONLY); I* megnyitjuk a kért állományt 7 if (fd < 0) fatal("open sikertelen"); while (1){ bytes = read(fd, buf, BUF_SIZE) /* olvasás az állományból 7 if (bytes <= 0) exit(o); /* vége van az állománynak? 7 write(sa, buf, bytes); /* bájtok kiírása a csatlakozóra 7 } close(fd); /* állomány lezárása 7 close(sa); /* összeköttetés lezárása 7 6.6. ábra. Folytatás

A SZÁLLÍTÁSI RÉTEG 537 A fatál függvény kitesz egy hibaüzenetet a kimenetre, majd kilép. A szervernek is szüksége van erre a függvényre, de a hely szűkös volta miatt nem írtuk le kétszer. A klienst és a szervert külön fordítják, és általában más számítógépeken futtatják, ezért nem oszthatják meg & fatál eljárás kódját. Ez a két program (a könyvhöz kapcsolódó többi anyaggal egyetemben) megtalálható a könyv weboldalán: http://www.prenhall.com/tanenbaum Itt a borító fényképe melletti Web Site" hiperhivatkozásra kell kattintania. A programokat bármely UNIX rendszerrel (pl. Solaris, BSD, Linux) le lehet tölteni és le is lehet fordítani a cc-o client client.c -Isocket -Insl cc-o server server.c -Isocket -Insl parancsok segítségével. A szerver indításához csak ezt kell begépelni: server A kliens indításához a fent már ismertetett két paraméter szükséges. A weboldalról a programok Windowsos változatai is letölthetők. A rend kedvéért meg kell említenem, hogy ez a szerver nem a legjobb a szerverek között. A hibaellenőrzése kevéssé alapos, a hibajelentései középszerűek, valamint agyafúrt módon sohasem hallott a biztonságról. A csupasz UNIX rendszerhívások használata sem a legjobb eszköz a platform-függetlenség eléréséhez. A program továbbá él néhány olyan, műszakilag lehetetlen feltételezéssel, mint például az a feltételezés, hogy az állománynév belefér a pufferbe, illetve, hogy automatikusan átvitelre kerül. A szerver teljesítménye gyenge, mert minden kérést szigorúan soros módon kezel (mivel csak egyetlen szálon fut). Mindezen hiányosságai ellenére azonban egy teljes és működőképes internetes állományszerver. A feladatokban az olvasót is buzdítjuk arra, hogy javítson ezen a két programon. A csatlakozók programozásával kapcsolatos további információért lásd (Stevens, 1997) művét. 6.2. A szállítási protokollok elemei A szállítási szolgálatot egy, a szállítási entitások között használt szállítási protokoll valósítja meg. Némely tekintetben a szállítási protokollok az adatkapcsolati protokollokra emlékeztetnek, amelyeket a 3. fejezetben tanulmányoztuk részletesen. Mindkettőnek többek között hibakezelést, sorszámozást és forgalomszabályozást kell végeznie. Ugyanakkor jelentős eltérések is vannak a kettő között. A különbségek fő oka abban az alapvetően eltérő működési környezetben rejlik, melyben a két protokoll működik. Ezt a 6.7. ábrán láthatjuk. Az adatkapcsolati rétegben a két csomópont közvetlenül egy fizikai csatornán keresztül kommunikál, míg a szállítási rétegben a fizikai

538 SZÁMÍTÓGÉP-HÁLÓZATOK Router Router Alhálózat Fizikai kommunikációs csatorna (a) (b) 6.7. ábra. (a) Az adatkapcsolati réteg környezete, (b) Szállítási réteg környezete csatorna helyett egy egész alhálózat szerepel. Ez a különbség fontos hatással van a protokollokra. Egyrészt az adatkapcsolati rétegben a routernek nem kell kijelölni, hogy melyik másik routerrel kíván kommunikálni - minden kimenő' vonal egyértelműen azonosít egy adott routert. A szállítási rétegben a cél explicit címzése kötelező. Másrészt, amikor egy folyamat a 6.7.(a) ábrán látható vezetéken összeköttetést akar létesíteni, egyszerű dolga van: a másik végpont mindig jelen van (hacsak el nem romlott, amikor is nincs jelen). Akármelyik eset következik is be, nincs sok tennivaló. A szállítási rétegben, mint látni fogjuk, a kezdeti összeköttetés-létesítés jóval bonyolultabb. Egy másik nagyon bosszantó különbség az adatkapcsolati és a szállítási réteg között az alhálózat potenciális adattároló képessége. Ha egy router elküld egy keretet, az vagy megérkezik, vagy elvész, de nem fog bolyongani egy darabig, elrejtőzni a világ egy távoli sarkába, majd hirtelen, egy váratlan pillanatban, mondjuk 30 másodperc múlva fölbukkanni. Ha az alhálózat a belső forgalmat datagramokkal és adaptív forgalomszabályozással valósítja meg, nem elhanyagolható annak a valószínűsége, hogy a csomagot valamelyik csomópont tárolja pár másodpercig, és csak ezután kézbesíti. Az alhálózat adattároló képességének következménye néha katasztrofális lehet, és speciális protokollok használatát teszi szükségessé. Az utolsó különbség az adatkapcsolati és a szállítási réteg között inkább mennyiségi, mint minőségi eltérés. Pufferelés és forgalomszabályozás mindkét esetben szükséges, de a szállítási rétegben jelenlevő nagy és változó számú összeköttetés eltérő megközelítést igényel, mint amit az adatkapcsolati rétegben használtunk. Néhány, a 3. fejezetben tárgyalt protokoll rögzített számú puffert rendel minden vonalhoz, így a beérkező keretek számára mindig van szabad puffer. A szállítási rétegben kezelendő nagyszámú összeköttetés láttán máris kevésbé vonzó ötlet mindegyiknek számos saját puffert lefoglalni. A következő alfejezetekben többek között ezekkel a fontos problémákkal fogunk foglalkozni. 6.2.1. Címzés Amikor egy alkalmazási folyamat (vagyis egy felhasználó) egy távoli alkalmazási folyamattal akar összeköttetést létrehozni, meg kell jelölnie, hogy melyik folyamattal akar kapcsolatba lépni. (Az összeköttetés nélküli szállítási szolgálatban is megvan ugyanez a probléma: Kinek kell elküldeni az egyes üzeneteket?) Az általánosan hasz-

A SZÁLLÍTÁSI RÉTEG 539 1. hoszt 2. hoszt Alkalmazási folyamat Szállítási összeköttetés! O 1208-as J>/TSAP f ^NSAP Alkalmazási réteg Szállítási réteg Hálózati réteg 1.szerver 2. szerver A \ 1522-es \ 1836-os TSAP \ f TSAP NSAP Adatkapcsolati réteg Fizikai réteg 6.8. ábra. A TSAP-k, az NSAP-k és a szállítási összeköttetések. nált módszer az, hogy külön szállítási címeket definiálunk az egyes folyamatok részére, amelyeken várhatják az összeköttetési kéréseket. Az Interneten ezeket a végpontokat általában portoknak hívják. Az ATM hálózatokban AAL-SAP a nevük. Mi a legáltalánosabb kifejezést, a TSAP-t (Transport Service Access Point - szállítási szolgálatelérési pont) fogjuk használni. Az ezekkel rokon végpontokat a hálózati rétegben (vagyis a hálózati rétegbeli címeket) ugyanígy NSAP-nak (Network SAP - hálózati szolgálatelérési pont) hívják. Az IP-címek például NSAP-k. A 6.8. ábra az NSAP, a TSAP és a szállítási összeköttetés összefüggéseit mutatja be. Az alkalmazási folyamatoknak, mind a kliens, mind a szervergépen egy helyi TSAP-re kell rákapcsolódniuk ahhoz, hogy egy távoli TSAP-vel összeköttetést tudjanak létrehozni. Ezek az összeköttetések az ábrán is látható módon mindkét hoszt NSAP-jén is keresztülhaladnak. Egyes hálózatokban minden számítógép csak egyetlen NSAP-vel rendelkezik, így szükség van egy olyan módszerre, amellyel több szállítási végpontot lehet megkülönböztetni egy NSAP-n belül. Erre a célra alkalmazzák a TSAP-ket. A szállítási összeköttetés egy lehetséges forgatókönyve: 1. A 2. hoszton található pontos idő folyamat az 1522-es TSAP-hez kapcsolódik és bejövő" hívásokra várakozik. Az, hogy egy folyamat hogyan tud egy TSAP-re rákapcsolódni, teljesen kívül esik a hálózat modelljén és kizárólag a helyi operációs rendszertől függ. A kapcsolódás történhet például egy a mi LiSTEN-ünkhöz hasonló hívással. 2. Az 1. hoszt egyik alkalmazási folyamata meg akarja tudni a pontos időt, ezért egy

540 SZÁMÍTÓGÉP-HÁLÓZATOK CONNECT hívásban megjelöli forrásként az 1208-as TSAP-t és célként az 1522-es TSAP-t. Ez végül az 1. hoszt alkalmazási folyamata és a 2. hoszt 1. szervere közötti összeköttetés kiépítéséhez vezet. 3. Az alkalmazási folyamat ezután elküldi a pontos időre vonatkozó kérését. 4. Az időszerver-folyamat a pontos idővel válaszol neki. 5. A szállítási összeköttetést ezután lebontják. Eközben persze a 2. hoszton más szerverek is várhatnak bejövő összeköttetési kéréseket. Ezek más TSAP-kre csatlakoznak, de az ezek számára érkező kérések is ugyanazon az NSAP-n keresztül érkeznek meg. Az itt lefestett kép nagyszerű, azonban egyetlen apró kérdést elegánsan a szőnyeg alá söpörtünk: Honnan tudja az 1. hoszt alkalmazási folyamata, hogy a pontosidőszerver az 1522-es NSAP-hez kapcsolódik? Az egyik lehetőség az, hogy az időszerver már évek óta az 1522-es NSAP-hez csatlakozik, és ezt szép lassan a hálózat minden felhasználója megtanulta. Ebben a modellben a szolgálatoknak stabil TSAP-címük van, amelyeket közismert helyeken megtalálható állományokban sorolnak fel. Ilyen például a UNIX rendszerek /etc/services állománya, amely felsorolja, hogy mely szerverek mely portokhoz vannak állandó jelleggel hozzárendelve. Habár a stabil TSAP-címek jól működnek kisszámú olyan szolgálat esetén, amelyek sohasem változnak (pl. webszerverek), a felhasználói folyamatok (általános értelemben) legtöbbször más olyan felhasználói folyamatokkal akarnak beszélgetni, amelyek csak rövid ideig léteznek, és nem rendelkeznek előre ismert TSAP-címmel. Ha mindezen felül sok olyan szerverfolyamat áll rendelkezésre a rendszerben, amelyeket csak ritkán használnak, akkor pazarló megoldás, ha mindegyik egész nap fut és egy stabil TSAP-címet figyel. Összefoglalva: jobb megoldásra van szükség. Egy ilyen megoldás egyszerűsített formája látható a 6.9. ábrán, amely kezdeti öszszeköttetés-protokollként (initial connection protocol) ismert. Ahelyett, hogy az összes lehetséges szerver egy jólismert TSAP-t figyelne, minden olyan gépnek van egy különleges folyamatszervere (process server), amely szolgálatokat akar felkínálni a távoli felhasználóknak. A folyamatszerver a kevésbé sűrűn használt szerverek megbízottjaként működik. Több portot figyel egyszerre, összeköttetési kérésekre várva. A szolgáltatásokat használni kívánók azzal kezdik a tevékenységüket, hogy kiadnak egy CONNECT kérést, amelyben megjelölik, hogy melyik TSAP-címen van az általuk igényelt szolgáltatás. Ha itt nem vár rájuk szerver, akkor a folyamatszerverrel kerülnek kapcsolatba, ahogyan az a 6.9.(a) ábrán is látható. Miután a folyamatszolgáltató megkapja a beérkező kérést, létrehozza a megfelelő szervert, aminek átadja a felhasználóval már fennálló összeköttetését. A szerver elvégzi a kért feladatot, miközben a folyamatszolgáltató továbbra is kérésekre várakozik. Ezt mutatja be a 6.9.(b) ábra. Míg a kezdeti összeköttetést létesítő protokoll ragyogóan működik olyan szerverek esetén, melyeket elegendő akkor létrehozni, amikor szükség van rájuk, sok eset van, amikor szolgáltatások a folyamatszolgáltatótól függetlenül léteznek. Például egy álló-

A SZÁLLÍTÁSI RÉTEG 541 1. hoszt 2. hoszt 1. hoszt 2. hoszt Pontos idő ^szerver. Folyamatszolgáltatóy 'Folyamat-.szolgáltatóy (a) 6.9. ábra. Az 1. koszton futó felhasználói folyamat és a 2. gépen futó pontos idő szerver közötti összeköttetés felépítése mányszolgáltatónak speciális hardveren (nagykapacitású merevlemezzel ellátott gépen) kell futnia, nem lehet csak úgy, menetközben létrehozni, amikor valaki használni akarja. Az ilyen esetek kezelésére gyakran egy alternatív módszert alkalmaznak. Ebben a modellben egy névszolgáltatónak (name server) vagy olykor katalógusszolgáltatónak (directory server) is nevezett speciális folyamat működik. Hogy a felhasználó egy adott szolgáltatás nevéhez (pl. pontos idő") tartozó TSAP-címet megtudja, összeköttetést létesít a névszolgáltatóval (ami a jól ismert TSAP-címén várakozik). A felhasználó üzenetet küld a kért szolgáltatás nevével, mire a névszolgáltató visszaküldi annak TSAP-címét. A felhasználó ezután megszünteti az összeköttetést a névszolgáltatóval, és újat létesít a kívánt szolgáltatással. Ebben a modellben egy új szolgáltatás létesítésekor a szolgáltatás nevével (rendszerint egy ASCII füzér) és TSAP-címével be kell jelentkezni a névszolgáltatónál, s az a kapott információt feljegyzi belső' adatbázisába. Ha később kérés érkezik erre a szolgáltatásra, tudni fogja a választ. A névszolgáltató feladata analóg a tudakozóéval a távbeszélőrendszerekben - nevekről számokra történő leképezést valósít meg. Éppúgy, mint a távbeszélőrendszerekben, lényeges, hogy a névszolgáltató (vagy kezdeti összeköttetést létesítő protokoll esetén a folyamatszolgáltató) jól ismert TSAP-címe valóban mindenki által ismert legyen. Ha nem tudjuk a tudakozó telefonszámát, nem lehet fölhívni a tudakozót, hogy megkérdezzük. Ha azt gondolnánk, hogy a tudakozó telefonszáma nyilvánvaló, próbáljuk meg valamikor fölhívni egy másik ország tudakozóját. (b)

542 SZÁMÍTÓGÉP-HÁLÓZATOK 6.2.2. Összeköttetés létesítése Az összeköttetés felépítése egyszerűnek tűnik, de valójában meglepően trükkös folyamat. Első pillantásra elegendő lenne, hogy az egyik szállítási entitás CONNECTION REQUEST TPDU-t küldene a másik félnek, és CONNECTION ACCEPT (ÖSSZEKÖTTETÉS ELFOGADVA) válaszra várna. A probléma akkor merül fel, ha a hálózat csomagokat veszít, tárol, vagy akár megkettőz. Ezek a lehetőségek komoly nehézségeket okoznak. Képzeljük el, hogy egy alhálózat annyira zsúfolt, hogy a nyugtázások nemigen érkeznek vissza időben, minden csomag időtúllépéssel érkezik meg, a csomagokat kétszer-háromszor újraküldik. Tegyük föl, hogy az alhálózat belül datagramokat használ, és minden csomag különböző útvonalon halad. Néhány csomag közlekedési dugóba kerülhet, és hosszú ideig nem érkezik meg, vagyis az alhálózat jelentős ideig tárolja őket, majd jóval később bukkannak elő. A létező legrosszabb rémálom a következő: egy felhasználó összeköttetést létesít egy bankkal, és üzenetet küld azzal a megbízással, hogy a bank utaljon át nagy pénzösszeget egy nem igazán megbízható személy számlájára, majd lebontja az összeköttetést. Szerencsétlenségére minden elküldött csomag megkettőződik, és valahol a hálózat mélyén tárolódik. Az összeköttetés befejezése után ezek sorban előbukkannak az alhálózatból, és helyes sorrendben megérkeznek a bankhoz újabb összeköttetést és tranzakciót kérve, majd ez az összeköttetés is megszűnik. A bank nem tudhatja, hogy kettőzött üzenetekről van szó. Feltételezi, hogy ez egy független, második tranzakció, így ismét átutalja a pénzt. Jelen alfejezetben a késleltetett kettőzések problémáját fogjuk tanulmányozni. Különös figyelmet szentelünk az összeköttetések megbízható módon történő létesítésére kifejlesztett algoritmusokra, hogy a föntiekhez hasonló rémálmok ne válhassanak valóra. A probléma alapvető oka a késleltetett kettőzések létezése. Többféle ellenszer létezik, de egyik sem teljesen kielégítő. Az egyik módszer azt mondja, hogy használjunk eldobható szállítási címeket. Ebben a megközelítésben minden esetben, amikor egy szállítási címre van szükség, újat generálunk. Az összeköttetés lebontása után a régi címet elvetjük, és soha nem használjuk újra. Ez a stratégia a 6.9. ábrán látható folyamatszolgáltató-modell működését lehetetlenné teszi. Egy másik lehetőség minden összeköttetésnek egy olyan egyedi összeköttetés-azonosítót adni (egy sorszámot, ami minden újabb összeköttetés létesítésekor eggyel nő), amit a kezdeményező fél generál és minden TPDU-ba (beleértve az összeköttetést kérőt is) beletesz. Az összeköttetés lebontása után minden szállítási entitás frissíti a befejeződött összeköttetések tábláját, amelynek bejegyzései (társ szállítási entitás, összeköttetés sorszám) párokból állnak. Minden újabb összeköttetés-kéréskor ellenőrizhető, hogy az nem egy régi összeköttetéshez tartozik-e. Sajnos ennek a módszernek van egy alapvető hibája: minden szállítási entitásnak határozatlan ideig történeti információt kell tárolnia. Ha egy gép összeomlik, és memóriatartalmát elveszti, többé nem tudja, hogy mely összeköttetés-azonosítót használta már. Ehelyett más megközelítést kell vennünk. Ahelyett, hogy egy csomagot örök időre életben hagynánk az alhálózatban, ki kell fejlesztenünk egy olyan mechanizmust, amely az öreg és még mindig bolyongó csomagokat kiirtja. Ha garantálni tudjuk, hogy

A SZÁLLÍTÁSI RÉTEG 543 egyetlen csomag sem él tovább egy adott idó'tartamnál, a probléma valamivel kezelhetőbbé válik. A csomagok élettartama ismert maximumra korlátozható az alábbi módszerek közül valamelyikkel: 1. Korlátozott alhálózat tervezése. 2. Átugrásszámláló (hop counter) alkalmazása a csomagokban. 3. A csomagok időbélyeggel való ellátása. Az első módszerbe minden olyan megoldás beletartozik, amely megelőzi, hogy a csomagok hurokba kerüljenek, és emellett valahogyan a torlódási késleltetést is korlátozni tudja a (pillanatnyilag ismert) leghosszabb lehetséges útvonalon. A második módszer abból áll, hogy az átugrásszámot valamilyen alkalmas értékre állítják be, és minden továbbadás alkalmával csökkentik. A hálózati protokoll minden olyan keretet egyszerűen eldob, amelynek az átugrásszámlál ója nullára csökkent. A harmadik módszerhez arra van szükség, hogy minden csomagot ellássanak a keletkezésének idejével, valamint a routereknek meg kell egyezniük abban, hogy eldobnak minden olyan csomagot, amely régebbi a közösen meghatározott legnagyobb lehetséges élettartamnál. Ez utóbbi módszer alkalmazásához a routerek óráit szinkronizálni kell, amely maga sem egyszerű feladat, hacsak nem a hálózaton kívül valósítják meg a szinkronizálást. Erre használhatunk például GPS-t vagy egy olyan rádióadót, amely periodikusan adatszórással közli a pontos időt. Gyakorlatban nem elég azt biztosítanunk, hogy egy csomag halott, hanem ennek igaznak kell lenni minden rá vonatkozó nyugtára is, ezért bevezetjük a T időtartamot, ami a valódi maximális csomagélettartam kis egész számú többszöröse. Az alkalmazott szorzó protokollfüggő, és szerepe egyszerűen csak T növelése. A csomag elküldését követően T idő várakozás után biztosak lehetünk abban, hogy a csomag már minden nyom nélkül eltűnt, és sem a csomag, sem a nyugtázások nem fognak hirtelen előtűnni a ködből, és további bonyodalmakat okozni. Korlátozott élettartamú csomagokat felhasználva bolondbiztos eljárást lehet kifejleszteni az összeköttetés biztonságos felépítésére. Az alább ismertetett eljárás Tomlinson nevéhez fűződik (1975). Ezzel ugyan megoldódik a probléma, viszont egyéb gondok jelentkeznek. A módszert továbbfinomította Sunshine és Dalai (1978), ennek különböző változatait széles körben alkalmazzák a gyakorlatban. Annak a problémának megkerülésére, hogy egy gép egy összeomlás után nem tudja megállapítani, hogy hol is tartott, Tomlinson azt javasolta, hogy minden hosztot időt mutató órával lássanak el. A különböző hosztokon levő óráknak nem szükséges szinkronban járniuk. Minden óra egy bináris számlálóval valósítható meg, ami egységes időközönként növeli értékét. Ezenkívül a számlálóban levő bitek számának egyenlőnek vagy nagyobbnak kell lennie, mint a sorszámokban levő bitek száma. Végül, ami a legfontosabb, a hoszt meghibásodásakor is tovább kell járnia az órának. Az alapötlet az, hogy az algoritmus nem engedi két azonos sorszámú TPDU egyidejű létezését. Az összeköttetés felépítésekor az óra értékének alsó k bitje alkotja a

544 SZÁMÍTÓGÉP-HÁLÓZATOK E N 52 o co 120 0 0 30 60 90 Idő (a) Összeomlás után 70-es sorszámmal újrakezdés _l I 120 150 180 használt sorszámok Idő (b) 6.10. ábra. (a) TPDU nem kerülhet a tiltott tartományba, (b) Az újraszinkronizációs probléma kezdeti (szintén k bites) sorszámot. így, eltérően a 3. fejezetben leírt protokolloktól, minden összeköttetés más sorszámmal kezdi számozni a TPDU-it. A használt tartománynak olyan nagynak kell lennie, hogy mire a sorszámok körbeérnek, az azonos sorszámú TPDU már rég eltűnjön. Ezt az időt és a kezdeti sorszámok közti lineáris összefüggést mutatja a 6.10. ábra. Ha valamikor a szállítási entitások már megegyeztek a kezdeti sorszámban, bármilyen csúszóablakos protokoll használható forgalomszabályozásra. Valóságban a kezdeti sorszám időfüggését jelző vastag görbe nem igazán egyenes, hanem lépcsőzött, mivel az óra értéke diszkrét lépésekben növekszik. Az egyszerűség kedvéért ezt a részletet elhanyagoljuk. Probléma akkor lép föl, ha egy hoszt összeomlik. Újraindulásakor a benne működő szállítási entitás nem fogja tudni, hogy milyen sorszámnál tartott. Az egyik lehetséges megoldás szerint, a szállítási entitások újraindulás után várjanak T ideig, hogy az öszszes régi TPDU addigra eltűnhessen. Egy összetett, több hálózatot összekapcsoló hálózatban azonban T igen nagy lehet, így ez a stratégia kevésbé vonzó. Egy összeomlás utáni T időtartamnyi tétlenség elkerülésére, a sorszámokra bevezetünk egy másik korlátozást is. Ennek szükségességét legkönnyebben egy példán keresztül mutathatjuk be. Legyen a maximális csomagélettartam, T, pontosan 1 perc. Az óra másodpercenként növeli értékét. Amint azt a 6.10.(a) ábrán látható vastag vonal is mutatja, az x időpontban fölépített összeköttetés kezdeti sorszáma x lesz. Tegyük föl, hogy t = 30 másodperckor egy közönséges adat TPDU indul a (már korábban létrehozott) 5-ös összeköttetésen keresztül 80-as sorszámmal, legyen ez az X TPDU. Közvetlen elküldése után a hoszt összeomlik, majd gyorsan újraindul. t= 60 pillanatban megkezdi 0-tól 4-ig terjedő sorszámú összeköttetéseit újra fölépíteni, t - 70-kor az 5- ös összeköttetést is újra létrehozza 70-es kezdeti sorszámmal, ahogy az elő van írva. A következő 15 másodperc alatt 11 TPDU-t küld el 70-től 80-ig terjedő sorszámokkal, így / = 85 másodperckor egy új, 80-as sorszámú TPDU indul el az 5-ös összeköttetésen keresztül az alhálózatban. Sajnos azonban az X TPDU még mindig létezik. Ha ez

A SZÁLLÍTÁSI RÉTEG 545 az új, 80-as számú TPDU előtt érkezik meg, a vevő az X TPDU-t fogadná el, és az igazi, 80-as számút mint kettőzést eldobná. Az ilyen problémák megelőzésére el kell kerülnünk a sorszámok használatát (azaz új TPDU-hoz rendelését) a potenciális kezdeti sorszámként történő alkalmazás előtti T időtartamban. Az illegális (sorszám-idő) párosítást a 6.10. ábrán látható tiltott tartomány jelöli. Bármely TPDU bármely összeköttetésen történő továbbítása előtt a szállítási entitásnak le kell olvasnia az óráját, hogy ellenőrizze, nem a tiltott tartományban van-e. A protokoll így is kétféleképpen kerülhet bajba. Ha egy hoszt túl gyorsan küld túl sok adatot egy frissen létesített összeköttetésen, az aktuális sorszám-idő görbe merehoszt 1. hoszt 2. hoszt Régi kettőzött ^7**/ ^ (<*<*. y) (b) 1. hoszt hoszt Régi kettőzött / D/ "7snr (tyű, '9ta: y) 6.11. ábra. Három forgatókönyv a háromutas kézfogás protokollal történő összeköttetéslétesítésre, CR és CA rendre CONNECTION REQUEST és CONNECTION ACCEPTED rövidítései, (a) Normális működés, (b) Régi kettőzött CR bukkan elő. (c) Kettőzött CR és kettőzött adat TPDU esete (c)