Transmission Control Protocol
A Transmission Control Protocol (TCP) az internet gerincét alkotó TCP/IP protokollcsalád egyik fő protokollja. A TCP a család két eredeti komponense közé tartozik, az Internet Protocolt (IP) egészíti ki, így együtt TCP/IP néven szokás hivatkozni rájuk. A TCP/IP protokollhierarchia szállítási rétegét valósítja meg. A TCP egy számítógépen futó program és egy másik számítógépen futó másik program között egy adatfolyam megbízható, sorrendhelyes átvitelét hivatott biztosítani. Az internet legfontosabb szolgáltatásainak nagy része TCP-n keresztül érhető el: ilyen pl. a World Wide Web és az e-mail. Más alkalmazások, melyeknél a kisebb késleltetés fontosabb a csomagvesztés elkerülésénél, a User Datagram Protocolt (UDP) használhatják.
A protokoll működése
szerkesztésA TCP egy kapcsolat-orientált protokoll, amely az OSI modell szállítási rétegében helyezkedik el. Fő feladata egy megbízható, és biztonságos kapcsolat kiépítése (és fenntartása) két folyamat között. Menetét alapvetően három részre bonthatjuk:
- Létrejön a megbízható kapcsolat két állomás között
- Lezajlik a tényleges adatátvitel
- A kapcsolat lezárása, és a számára elkülönített erőforrások felszabadítása.
A protokoll a hibamentes átvitelhez az úgynevezett pozitív nyugtázás újraküldéssel (positive acknowledgement with retransmission) néven ismert eljárást használja. A TCP kapcsolatok egyes lépéseit állapotoknak nevezzük. A kapcsolat élettartama alatt különböző állapotváltozásokon megy keresztül:[1]
- A leírásban szereplő három rövidítés TCP üzenettípusokat jelöl, melyeket a fejlécben szereplő megfelelő bitek segítségével lehet változtatni.
- SYN: szinkronizációs üzenet, kapcsolat létrehozására, ill. fenntartására irányuló kérés. Emellett a sorszámok szinkronizálása is ezen bit segítségével történik.
- FIN: kapcsolat bontására irányuló kérés.
- ACK: nyugtázó üzenet, SYN/FIN üzenetre küldött válasz, ezzel jelezvén az üzenet átvételét.
- CLOSED: ez az alapértelmezett állapot, amelyből a kapcsolat kiépítésének folyamata indul. Elméleti állapot, a felek között nincs létező kapcsolat (még nem jött létre, vagy már lezárult).
- LISTEN: az állomás (általában a szerver) szinkronizálási kérésre várakozik (SYN), saját SYN üzenetét még nem küldte el.
- SYN-SENT: az állomás (általában a kliens) elküldte a SYN üzenetet, és várakozik a válaszra a másik féltől (szerver).
- SYN-RECEIVED: kapcsolódási kérés (SYN) elküldve és fogadva is, várakozás a másik fél általi nyugtázás beérkezésére (ACK).
- ESTABLISHED: a „stabil állapota” egy létrejött TCP kapcsolatnak. Miután mindkét állomás ebbe az állapotba kerül, megkezdődhet az adatok átvitele, ami addig folytatódik, amíg a kapcsolat lezárását egyik fél se kezdeményezi.
- CLOSE-WAIT: az állomás kapcsolatbontási kérést (FIN) kapott a másik féltől. Várakozik a helyi alkalmazás nyugtázására, mielőtt elküldené a megfelelő válaszüzenetet.
- LAST-ACK: az állomás már fogadott és nyugtázott egy kapcsolatbontási kérést, elküldte a saját FIN üzenetét, és várakozik a másik fél ezen kérésre érkező nyugtájára (ACK).
- FIN-WAIT-1: várakozás az elküldött FIN üzenet nyugtázására, vagy a kapcsolatbontási kérés érkezésére másik féltől.
- FIN-WAIT-2: megérkezett a nyugta az elküldött kapcsolatbontási üzenetre, várakozás a másik fél FIN üzenetére.
- CLOSING: az állomás megkapta a másik fél FIN üzenetét, és nyugtázta azt, de a saját FIN üzenetére nyugtát még nem kapott.
- TIME-WAIT: a kapcsolatbontási kérést és a nyugtát (FIN, ACK) az állomás megkapta és kiküldte, a kapcsolat lezárult. Egy rövid ideig várakozik még, hogy biztosítsa a másik fél megkapta a nyugtát, és ne legyen átfedés az újonnan létrejövő kapcsolatokkal.
A kapcsolat létrehozása
szerkesztésA TCP protokoll ellentétben az UDP-vel kapcsolatorientált, megbízható összeköttetést biztosít két eszköz között. Egy kapcsolat általános menete a következő:
- Az adatátvitel megkezdéséhez a forrás-, és a célalkalmazás értesíti az operációs rendszert a kapcsolat létrehozási szándékáról.
- Az egyik csomópont kezdeményezi a kapcsolatot, a másiknak pedig fogadnia kell azt.
- A két operációs rendszer protokoll-szoftvermoduljai a hálózaton elküldött üzenetekkel kapcsolatba lépnek egymással és ellenőrzik, hogy az adatküldés engedélyezett-e, illetve, hogy mindkét oldal készen áll-e.
- Ezután a kapcsolat létrejön, a szükséges szinkronizálások elvégzése után pedig megkezdődik az adatok átvitele.
- Az átvitel során a két készülék protokollszoftverei közötti kapcsolat a megérkezett adatok helyességének ellenőrzése céljából változatlanul fennmarad.
Háromfázisú kézfogás
szerkesztésAz adatátvitel megkezdése előtt kapcsolatot kell létesíteni a két végpont között. Mivel egy TCP szegmensben a maximálisan szállítható adat mérete korlátos (MTU), a protokollnak fel kell darabolnia az ennél nagyobb méretű adatfolyamot, majd a másik oldalon ugyanazon sorrendben vissza kell állítani azt (a megfelelő sorszámok alapján). A kapcsolat létrehozásakor szükséges így mindkét fél kezdő sorszámának egyeztetése, melyet a SYN vezérlőbittel megjelölt szegmensek elküldésével tesznek meg. Ezt a kapcsolódási folyamatot nevezzük háromfázisú kézfogásnak, melynek lépései a következők:
- Forrásállomás (A) kezdeményezi a kapcsolatlétrehozását a célállomással (B), egy SYN szegmens elküldésével, melyben jelzi kezdősorszámát is (seq=x).
- B megkapja a szegmenst és feljegyzi az A állomás kezdősorszámát, majd küld egy nyugtát a következő szegmens sorszámával (ack=x+1), és saját kezdő sorszámával (seq=y). Ezzel jelzi, hogy épségben megkapta x-edik oktettig a szegmenst, és várja x+1-edik sorszámtól a többi darabot.
- Az A állomás megkapja a választ, melyből megtudja a B állomás kezdő sorszámát (y) és elküldi a következő szegmenst, egyben nyugtázva is a kérést (ack=y+1).
Ezután megkezdődik az adatok átvitele, és a kapcsolat mindaddig nyitva marad, amíg bármelyik fél nem kéri annak lezárását.
Ablakozás
szerkesztésAz adatátvitel gyorsítása érdekében a TCP protokoll nem várja meg a nyugtát minden egyes szegmens elküldése előtt, mivel az nagyon lassú kapcsolatot eredményezne, helyette több szegmens elküldését is engedélyezi a nyugta beérkezése előtt. Mivel a hálózaton található eszközök és állomások tulajdonságai eltérőek, fontos egy adatfolyam-vezérlési mechanizmus meghatározása az ilyen protokollok esetén. Ennek hiányában a küldő fél könnyen túlterhelheti a fogadó felet, megfelelően nagy számú szegmens küldésével, és így az adatok egy része elveszik (a csomagokat nem lehet újra összeilleszteni a célállomáson). A TCP esetén ezt az adatfolyam-vezérlési mechanizmust „ablakozásnak”, a nyugta előtt elküldhető szegmensek számát pedig ablakméretnek (vagy röviden ablaknak) nevezzük. A kifejezés arra utal, hogy a kapcsolatban kommunikáló felek dinamikusan határozzák meg az elküldhető szegmensek számát (vagyis az ablakméretet).
- Az ablakozás megköveteli, hogy a forrás adott mennyiségű adat elküldése után nyugtát kapjon a céltól. A TCP erre várományos nyugtákat használ, tehát minden nyugtában a következőként várt csomag sorszáma szerepel (vagyis nem kell minden csomag után egy külön nyugtát küldeni).
- Ha a célállomás nem kapja meg a csomagot, akkor nem küld róla nyugtát. Amennyiben a forrás nem kap nyugtát az elküldött csomagról, akkor tudja, hogy a sebességet csökkentenie kell és újra kell küldeni a nem nyugtázott szegmenseket.
- A fogadó közli az ablakméretet a küldő féllel, ami megadja, hogy hány szegmens vételére van felkészülve, és az ezen felül küldött szegmenseket figyelmen kívül hagyja. Az első érkező szegmens az ablakméret nyugtázása.
Folyamat menetére példa:
- Forrás el szeretne küldeni, 6 KB-nyi adatot a célállomásnak, ezért kapcsolatot kezdeményez vele.
- A kapcsolat létrejön, majd a fogadó fél elküldi az ablakméretét (WIN=4096). Ezután a forrásállomás elküld 4 KB-nyi adatot, 1 KB-os szegmensekben.
- A fogadó fél megkapja és nyugtázza a szegmenseket, majd értesíti a másik állomást, hogy ne küldjön többet, a puffere megtelt (ACK=4096, WIN=0).
- A forrásalkalmazás elküld 2 KB adatot. Mivel az ablakméret 0, meg kell várnia, amíg a vevő feldolgozza a korábbi adatokat. Ha ezalatt új csomagot küld, azt a fogadó egyszerűen eldobja, és nem küld róla nyugtát (Feladó blokkolva).
- Amint a vevő feldolgozta az adatok egy részét, értesítést küld a forrásnak egy új ablakmérettel (ACK=4096, WIN=2048). Ezután újra megkezdődhet az adatátvitel.
- A küldő továbbítja a maradék 2 KB adatot, majd várja a nyugtát.
- Vevő nyugtázza a beérkezett adatokat és elküldi az aktuális ablakméretét (ACK=6144, WIN=1024). Miután a küldő állomás megkapja a nyugtát, kezdeményezi a kapcsolat lezárását, mivel nincs több küldésre váró adata.
Nyugtázás
szerkesztésA megbízható kézbesítés garantálja, hogy a kommunikáció során elküldött adatok veszteség, vagy kettőződés nélkül elérik a céljukat. Ennek érdekében a hibamentes átvitelhez, a TCP protokoll, az úgynevezett pozitív nyugtázás újraküldéssel (positive acknowledgement with retransmission) néven ismert eljárást használja. Formailag az elküldött összes oktett sorszámmal rendelkezik, és minden egyes elküldött szegmens, SEQ mezője határozza meg az abban szereplő legelső oktett sorszámát (mérete pedig a legutolsóét). A másik oldalon a fogadó fél a beérkezett szegmensek ACK mezőjében visszaküldött számmal jelzi a következőként várt szegmens sorszámát, ezzel nyugtázva az ennél kisebb sorszámú szegmensek sikeres fogadását is. A fogadó fél által küldött nyugta még nem azt jelenti, hogy a szegmenst kézbesítette a végfelhasználónak, csak átadta ennek felelősségét a másik oldali TCP folyamatnak.
Amikor a TCP elküld egy adatokat tartalmazó szegmenst a hálózaton, elhelyez egy másolatot az újraküldési sorban is, és elindít egy időzítőt; majd amint megérkezik a másik féltől a nyugta, törli a szegmenst a sorból. Ha az időzítő lejárta előtt mégse kap nyugtát a küldő fél (vagyis a célállomás feltehetően nem kapta meg a csomagot), akkor a szegmenst újraküldi. Az időzítő értékének meghatározásához a TCP méri az átlagos RTT-t (Round trip delay time - az az idő, ami alatt a csomagot elküldjük, és visszaérkezik rá a nyugta), és ennél egy kicsivel nagyobb értékre állítja be azt.[3]
Szelektív nyugtázás
szerkesztésHa az adatátvitel során néhány csomag után nem érkezik meg a nyugta, a TCP által eredetileg meghatározott kumulatív nyugtázás[4] alkalmazásával az újraküldés feleslegesen nagy sávszélességet vehet igénybe. Például van 1 KB-nyi adatunk, amit 100 bájtos szegmensekben szeretnénk továbbítani a hálózaton. Ha az összesen elküldendő 11 szegmensből az első és a második csomag elveszik az átvitel során, akkor (kumulatív nyugtázással) az újraküldendő két csomag helyett mind a 11 csomagot ismét el kellene küldenünk.
Ennek kivédése érdekében bevezették az úgynevezett szelektív nyugtázást, mellyel a fogadó fél jelezni tudja mely csomagokat kapta meg hibamentesen, és így elég csak az elveszett csomagokat újraküldeni. A TCP header „OPTIONS” mezőjében lévő SACK (selective acknowledgement) beállítással tudjuk ezt befolyásolni, amiben megadhatjuk a helyesen megkapott szegmens határait.[5] A fenti példában a fogadó fél a SACK üzenetben a 200 és 1023-as sorszámokat küldené el. Így a forrás tudná, hogy elég csak az első két csomagot, 0-199 bájtig elküldeni.
A SACK használata nem kötelező és csak akkor használják, ha mindkét fél támogatja (ezt kapcsolódáskor egyeztetik).
Később kiadtak egy kiegészítést a SACK opcióhoz, mellyel már a feladó képes észrevenni a duplán újraküldött csomagokat is (D-SACK, duplicate-SACK). Így amikor a nyugták sorrendjének helytelensége miatt a feladó azt feltételezi, hogy néhány csomag elveszett és azokat újraküldi, a vevő oldal jelezheti a kettőződést, ezzel is gyorsítva az adatátvitelt. Ez teljesen kompatibilis az előző verzióval, ha mindkét fél támogatja a SACK használatát, a D-SACK-et is lehet használni. Bár ez a kiegészítés csak akkor működik, ha mindkét fél támogatja, de ellenkező esetben sem okoz problémát.[6]
TCP felépítése
szerkesztésOffsets | Octet | 0 | 1 | 2 | 3 | ||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Octet | Bit | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
0 | 0 | Source port | Destination port | ||||||||||||||||||||||||||||||
4 | 32 | Sequence number | |||||||||||||||||||||||||||||||
8 | 64 | Acknowledgment number | |||||||||||||||||||||||||||||||
12 | 96 | Data offset | Fenntartva | N S |
C W R |
E C E |
U R G |
A C K |
P S H |
R S T |
S Y N |
F I N |
Window Size | ||||||||||||||||||||
16 | 128 | Checksum | Urgent pointer | ||||||||||||||||||||||||||||||
20 ... |
160 ... |
Opciók és Padding |
Jegyzetek
szerkesztés- ↑ The TCP/IP Guide - Table 151: TCP Finite State Machine (FSM) States, Events and Transitions
- ↑ The TCP/IP Guide - TCP Connection Establishment Process: The „Three-Way Handshake”
- ↑ RFC 793, 2.6 alfejezet (9. oldal)
- ↑ RFC 793, 3.3 alfejezet (24. oldal)
- ↑ RFC 2018, 1. fejezet (1. oldal)
- ↑ RFC 2883, 1. fejezet (2. oldal)
Források
szerkesztés- Charles M. Kozierok. The TCP/IP Guide: A Comprehensive, Illustrated Internet Protocols Reference. No Starch Press. ISBN 1-59327-047-X (2005) Online változat
- RFC 793
- RFC 2018
- RFC 2883