CATEGORII DOCUMENTE |
Subsections
A. Caracteristici UDP
UDP (User Datagram Protocol) este un protocol de nivel transport construit special pentru a oferi un serviciu de comunicare cat mai simplu peste IP. Specificatiile protocolului au fost publicate in 1980 in RFC-ul cu numarul 7681.
Cateva caracteristici ale UDP-ului sunt:
Cateva utilizari tipice ale UDP-ului:
RFC 768 are nici mai mult nici mai putin decat 3 pagini; nu contine cuprins dar are o lista de 5 referinte bibliografice
Datagramele UDP sunt formate dintr-un antet (figura 7.1) urmat de datele care se doresc transmise (daca exista).
Antetul cuprinde:
Impreuna cu adresa IP a sursei acest numar identifica in mod unic locul de unde a fost trimis datagrama UDP;
Impreuna cu adresa IP a destinatiei acest numar identifica in mod unic destinatia dorita pentru datagrama UDP;
Lungimea minima masoara datagrama UDP cu tot cu antent si prin urmare are o valoare minima de 8 octeti.
Suma de control acopera intreg pachetul UDP cat si un pseudo antet de 12 octeti format din:
Deoarece suma de control necesita in calculul ei un numar multiplu de 16 octeti, la sfarsitul datelor se adauga un numar potrivit de octeti de zero. Daca suma este 0 atunci ea va fi stocata ca 65535 (toti bitii pe 1). Un 0 in campul de sumei de control indica faptul ca suma de control nu a fost calculata. Observatie: chiar daca un client are inhibat (in mod explicit) calcului sumei de control el este obligat sa verifice suma pachetelor care sosesc si au suma calculata.
Subsections
Deoarece protocolul IP este de tip datagrama utilizarea lui direct
in aplicatii, care in general au nevoie de conexiuni sigure, este mult
prea anevoioasa. Din aceste motive peste IP a fost construit un alt
protocol, TCP (transimission control protocol), care corecteaza aceste
probleme. Prima definire se gaseste in RFC-ul cu numarul 793
si dateaza din septembrie 1981. Din cauza deselor congestii
aparute in 1986 algoritmul care sta la baza TCP-ului este reanalizat
si in octombrie 1989 in RFC-ul cu numarul 1122 este publicata o
noua specificare, mult mai eficienta si neambigua, a TCP-ului.
Noi probleme legate de viteze mari sunt tratate in RFC-ul 1323 iar in 2018
TCP-ul este extins pentru a permite confirmarile selective (selective
acknowledge). Seria de RFC-urie fundamentale este incheiata de aparitia in
Transferul sigur de date este asigurat in urmatorul mod:
Serviciul oferit de TCP este de tip flux de octeti deoarece ofera garantii ca fluxul de date trimis de sursa va fi livrat fara modificari la destinatie. Comparativ, UDP-ul produce pentru fiecare transfer cerut de nivelul aplicatie, un pachet IP (care ulterior poate fi supus fragmentarii) care, daca ajunge la destinatie corect va fi livrat direct nivelului aplicatie fara a garanta in vreun fel ordinea.
Pachetele de date transmise de TCP, segmentele, sunt formate dintr-un antet (figura 7.2) de 20 octeti urmat de datele primite de la nivelul aplicatie. Antetul poate uneori contine si o serie de optiuni, caz in care poate ajunge la 60 octeti.
Antetul unui segment TCP cuprinde:
Aceste doua porturi, impreuna cu adresele ale sursei si destinatiei continute in antet-ul IP identifica in mod unic conexiunea. Pentru o pereche formata dintr-o adresa IP si un port se foloseste adesea denumirea de socket (denumire introdusa in specificatiile initiale ale protocolului TCP, in RFC 793).
Pentru a asigura un serviciu de tip flux de octeti TCP numeroteaza fiecare octet de date utilizand un numar de secventa. Numarul de secventa din cadrul antetului TCP specifica destinatiei care este primul octet din fluxul trimis. La initierea unei conexiuni, se seteaza flag-ul SYN si se alege aleator un numar de secventa de inceput utilizand un generator de numere de secventa, ISN (Initial sequence number). Numarul de secventa al primului octet de date va fi numarul generat, ISN, plus 1, deoarece pachetul de initiere (cu SYN setat) consuma si el un numar de secventa. Se va vedea mai departe ca si flag-ul de terminare a conexiunii, FIN, consuma si el un numar de secventa.
Reprezinta numarul de secventa al octetului de date pe care transmitatorul confirmarii se asteapta sa-l primeasca. Astfel, daca s-a receptionat octetul cu numarul de secventa x (in numerotatia sursei) pachetul de confirmare va avea flag-ul ACK setat si va contine numarul de confirmare x + 1. Trimiterea unui ACK nu consuma un numar de secventa deoarece atat acest camp cat si flag-ul ACK fac parte din antet, si, dupa stabilirea conexiunii ambele campuri devin active. Acest mecanism nu permite confirmari selective pentru ca numarul de secventa specifica pana unde s-au receptionat date. De exemplu, daca la destinatie au ajuns octetii 1-1024 si urmatorul segment primit contine octetii 2049-3072 nu se poate trimite confirmare pentru cel de-al doilea segment, deci confirmarea va cuprinde numarul de secventa 1025.
Specifica dimensiunea antetului ca numar de cuvinte de 32 de biti (4 octeti). Antetul poate avea intre 20 si 60 de octeti, deci valoarea acestui camp va fi intre 5 (5 x 4 = 20 octeti) si 15 (15 x 4 = 60).
Reprezinta numarul de octeti (incepand cu numarul de secventa continut in campul de confirmare) pe care destinatia e dispusa sa-l primeasca. Este limitat la 65535 octeti dar, cu toate ca pare o limita destul de mare, exista situatii cand se doresc valori mult mai mari. In acest scop se folosesc niste optiuni speciale descrise ceva mai tarziu, care permit scalarea ferestrei.
Aceasta suma de control acopera intregul segment TCP (atat datele cat si antetul TCP) si, spre deosebire de UDP, este obligatoriu sa fie completat de transmitator si verificat de receptor. Dar, ca si in cazul UDP-ului, la calculul sumei de control se ia in considerare si o zona speciala de 12 octeti ce cuprinde pentru re-verificare campuri din antetul IP (adresa IP a sursei si a destinatiei)[aici tre sa' vina o referire la poza cu pseudo-antetu]. Dupa adaugarea acestui pseudo-antet datele se impart in cuvinte de 16 biti in vederea calcularii sumei de control, adaugandu-se eventual si un octet de aliniere.
Este utilizat pentru specificarea deplasamentului ultimului octet de date trimis in regim urgent. Astfel, ultimul octet din secventa urgenta se obtine adunand acest camp la numarul de secventa. Ce inseamna acest mod urgent de transmitere: exista situatii in care aplicatiile vor sa trimita date `neordonate`. Sa presupunem ca aplicatia a trimis catre nivelul transport o cantitate mare de date dar la un moment dat observa ceva in neregula si doreste sa anuleze operatia. Daca trimite o comanda de anulare aceasta va fi adaugata la sfarsitul sirului de octeti deci nu se va putea impiedica ajungerea acestora la nivelul aplicatie de la receptor. Activand modul urgent datele urgente (comanda de anulare) vor fi plasate la inceputul pachetului. Aplicatiile mai cunoscute care folosesc acest mod sunt Telnet, Rlogin si FTP.
Cele mai utilizate optiuni sunt:
Este utilizat pentru alinierea datelor continute in campul de optiuni. Nu poate fi utilizat decat o singura data, marcandu-se astfel sfarsitul optiunilor si inceperea datelor efective. Daca pentru alinierea la un cuvant de 32 de biti e nevoie de mai mult de 1 byte se va utiliza optiunea no operation. Orice apare dupa aceasta optiune pana la inceputul cuvantului urmator de 32 de biti e ignorat.
Utilizat pentru alinierea la cuvinte de 32 de biti.
In ciuda denumirii defineste lungimea maxima a datelor, nu dimensiunea intregului segment. Poate lua valori intre 0 si 65535, valoarea implicita fiind 536. Aceasta optiune e valabila doar in pachetele de initiere a conexiunii (cele cu flag-ul SYN setat), fiecare parte facand cunoscuta dimensiunea maxima a datelor dispusa sa le primeasca intr-un pachet. In principiu cu cat aceasta valoarea e mai mare e mai bine, (deoarece se recupereaza din spatiul ocupat de antetele TCP si IP) pana cand apare fragmentarea. Valoarea maxima la care se poate seta este MTU (Maximum Transfer Unit) minus dimensiunea antetului IP si TCP (1460 octeti in cazul Ethernet).
Pentru situatiile in care se doreste utilizarea unei ferestre mai mare de 65535 bytes se poate utiliza acest camp pentru marirea dimensiunii ferestrei. Noua dimensiune va fi: . Chiar daca factorul de scalare poate fi maxim 255, in cazul TCP/IP el nu poate depasi valoarea 16, deoarece dimensiunea maxima a ferestrei nu poate fi mai mare decat valoarea celui mai mare numar de secventa ( ).
Acest factor se poate seta doar la initierea conexiunii. In timpul transferului de date se poate modifica dimensiunea ferestrei dar factorul de scalare ramane acelasi. Daca cel care a initiat conexiunea a trimis in segmentul de initiere si acest factor dar in pachetul cu ACK destinatarul nu si-a trimis si el factorul, atunci se la considera 0 in ambele directii. Invers, daca cel care solicita deschiderea conexiunii nu seteaza factorul, destinatia nu va putea seta factorul de scalare.
Utilizat pentru retinerea timpului in vederea calcularii RTT (Round Trip Time). Campul timestamp e completat de sursa in momentul trimiterii segmentului. La destinatie valoarea este retinuta si copiata in campul timestamp echo reply al pachetului cu confirmarea. RTT-ul este calculat de sursa facand diferenta dintre timpul curent si aceasta valoare.
TCP este un protocol orientat conexiune, deci presupune stabilirea unei cai virtuale intre sursa si destinatie.
Subsections
C.1 Protocolul de initiere
Modul de transmisie in cazul protocolului TCP este full-duplex, deci sunt transmise date simultan in ambele directii. Aceasta presupune ca cel care initiaza conexiunea trebuie sa primeasca aprobarea celuilalt capat inainte de inceperea transferului de date: sursa isi anunta intentia de a initia o conexiune, destinatia trimite un pachet cu confirmarea cererii si un pachet de initiere a conexiunii de la el la sursa iar apoi sursa confirma cererea primita de la destinatie. Pasii 2 si 3 pot fi realizati prin trimiterea unui singur pachet, de aceea protocolul de initiere este cunoscut sub numele de three-way handshake.
In cadrul protocolului de initiere exista 2 tipuri de cereri de initiere: cerere activa (active open), initiata de clientul ce doreste sa stabileasca conexiunea cu serverul si cerere pasiva (passive open), din partea serverului.
Cei 3 pasi sunt:
Se poate intampla ca uneori cele doua capete care vor sa comunice sa incerce sa stabileasca conexiunea simultan. In acest caz, dupa ce fiecare a trimis segmentul de initiere (initiere activa), ambele vor trimite un segment cu SYN + ACK si se va stabili o singura conexiune, nu doua.
Oricare dintre cele doua parti poate solicita inchiderea conexiunii, dar conexiunea fiind full-duplex, transferul de date in celalalt sens poate continua (aceasta situatie e denumita half-close). O inchidere completa a unei conexiuni TCP presupune urmatorii pasi:
Cel care initiaza primul procedura de inchidere (trimite primul FIN) realizeaza o inchidere activa (active close) iar celalalt capat o inchidere pasiva (passive close). In mod normal cel care realizeaza initierea activa va fi primul ce va trimite FIN, dar oricare dintre cei doi poate inchide activ conexiunea.
Subsections
In mod similar cu deschiderea simultana exista posibilitatea ca ambele capete ale conexiunii TCP sa initieze simultan procedura de inchidere a conexiunii. In acest caz ambele parti vor trimite FIN si vor astepta primirea unui ACK. In continuare fiecare va primi cererea de terminare si va trimite ACK. Se observa ca numarul de segmente transferate pentru realizarea inchiderii conexiunii (4 segmente) este acelasi ca la terminarea normala.
Exista situatii in care TCP doreste resetarea conexiunii. De exemplu daca se solicita initierea unei conexiuni la un port inexistent. In acest caz cealalta parte va trimite un segment cu bitul RST setat pentru a anula solicitarea. O alta situatie este atunci cand se constata ca celalalt capat al conexiunii nu raspunde un anumit timp (timeout).
Toate evenimentele ce au loc in timpul stabilirii conexiunii, transferului si inchiderii conexiunii pot fi rezumate printr-un automat finit cunoscut sub numele de diagrama de stari. Dupa cum chiar numele sugereaza este o masina cu un numar limitat de stari. O stare este pastrata pana in momentul aparitiei unui eveniment, moment in care se poate trece in alta stare si/sau efectua o actiune.
Aceste stari posibile sunt (denumirile sunt asemanatoare cu cele utilizate de netstat) cele din tabelul 7.1.
Tabela: Starile diagramei de stari TCP |
||||||||||||||||||||||||
|
In diagrama ilustrata in figura 7.4 putem observa 3 tipuri de tranzitii intre cele 11 stari: tranzitii ce corespund unei functionari normale pentru client (linii normale, continue), pentru server (linii normale, intrerupte) si tranzitii pentru situatii nestandard (linii subtiri, continue).
O comportarea normala pentru client presupune parcurgerea urmatoarelor stari: CLOSED, SYN_SEND, ESTABLISHED, FIN_WAY_1, FIN_WAY_2, TIME_WAIT:
Din punctul de vedere al unui server o comportare standard parcurge urmatoarele stari: CLOSED, LISTEN, SYN_RCVD, ESTABLISHED, CLOSE_WAIT si LAST_ACK:
Atat serverul cat si clientul TCP se pot afla in oricare din cele 11 stari ale diagramei.
D. Controlul fluxului
Daca inca de la inceput s-a reusit stabilirea formatului unui pachet TCP si a modulului in care trebuie sa se faca inchiderea si deschiderea unei conexiuni, nu acelasi lucru se poate spune si despre modul in care ar trebui sa se realizeze controlul fluxului. Tinand seama insa ca din 1989 (de cand dateaza RFC-ul 2581, cel despre care am mentionat ca specifica in mod clar modul in care trebuie sa se comporte o implementare de TCP) TCP-ul a ramas neschimbat putem sa il consideram un rezultat important al domeniului retelor de calculatoare.
In cele ce urmeaza vom intelege prin controlul fluxului totalitatea algoritmilor care permit atingerea unei viteze de transfer punct-la-punct cat mai mare pentru toate conexiunile existente. In principal acesti algoritmi stabilesc modul in care segmentele si confirmarile trebuie trimise si ce actiuni trebuie executate in situatiile in care raspunsurile asteptate de la celalalt capat intarzie sa vina.
Subsections
O modalitate simpla de generare a confirmarilor este de a trimite cate una pentru fiecare segment primit. Aceasta politica prezinta avantajul de a face comunicatia self-clocking insa este ineficienta daca segmentele care nu contin decat confirmari sunt urmate la scurta distanta (cateva zeci de milisecunde) de segmente ce contin date efective. Pentru a evita aceasta situatie se procedeaza2 la intarzierea (200ms este o valoare uzuala; in RFC 1122 se specifica o valoare maxima de 500ms) a segmentelor care contin doar confirmari. Aceasta strategie face posibil ca un raspuns generat de primirea unor date sa plece sper celalalt capat in acelasi segment cu confirmarea.
Observatie: deoarece este dificil de mentinut timere pentru fiecare confirmare diferenta de 200ms este calculata de un timer global. Din acest motiv modul efectiv de comportare poate fi descris si in felul urmator: cand un segment nu contine decat o confirmare el este pus intr-o coada ce va fi inspectata de un proces care din 200 in 200 ms trimite tot ce s-a acumulat in coada.
Acest comportament a fost propus de David D. Clark in iulie 1982 in RFC 813
Acest algoritm3 incearca sa imbunatateasca performantele exploatand urmatoarea caracteristica foarte des intalnita in dialogul dintre doua statii: daca se incearca trimiterea unor date de dimensiune mica insa exista inca date neconfirmate de partener atunci ele sunt buffer-ate si trimise intr-un segment mai mare cand soseste confirmarea asteptata. In acest fel se poate evita generarea datagramelor mici (tinygrame) in situatia unei legaturi lente. In cazul unei legaturi rapide confirmarile vor veni repede si intarzierea introdusa de algoritm va neglijabila.
Exista insa
si cazuri in care acest algoritm duce la deprecierea performantelor:
mesajele scurte generate de miscarile mouse-ului in cazul folosirii
unui server X Window sau utilizarea tastelor care trimit mai mult de un caracter (secvente escape). Pentru a rezolva aceste
inconveninte API-ul de utilizare a TCP-ului trebuie sa
ofere o modalitate de a dezactiva acest algoritm (in sistemele bazate pe
socketi exista in acest scop optiunea TCP_NODELAY
algoritm3
Algoritmul apartinand lui John Nagle a fost propus in ianuarie 1984 in RFC 896
Algoritmul implementat de TCP pentru a implementa transferul sigur de date este cunoscut in teorie sub numele de Go-Back-N. In acest algoritm se utilizeaza numere de secventa pentru a distinge pachetele intre ele si o coada (dimensiunea maxima a cozii reprezinta fereastra) de pachetele a caror confirmare se asteapta. Pachetele se impart in 4 categorii:
Daca confirmarile pentru pachetele din categoria 2 intarzie prea mult (un mecanism de timer-e informeaza asupra acestui lucru) atunci ele vor fi retrimise. In versiunea initiala TCP-ul nu permitea decat confirmari pozitive ceea ce inseamna ca avansarea ferestrei se va impotmoli la segmentele neconfirmate. Cum se poate evita aceasta situatie vom discuta in detaliu in capitolele urmatoare. O solutie foarte radicala o constituie introducerea de confirmari selective (acest lucru este realizat de RFC 2018 din octombrie 1996). Aceasta modifica face ca TCP-ul actual sa fie un hibrid de Go-Back-N si Selective Repeat.
Deoarece dimensiunea ferestrei este anuntata la fiecare segment un client lent poate ca pe masura ce trimite confirmarile sa informeze despre progresul inregistrat la livrarea datelor urmatorului nivel (aplicatie). Daca datele vin prea repede pentru viteza cu care clientul proceseaza datele fereastra fereastra se va dimiua si chiar inchide (acest lucru se realizeaza anuntand o fereastra de dimensiune zero). Cum se realizeaza efectiv redeschiderea vom analiza intr-un capitol viitor.
Un transfer de date TCP poate sa inceapa prin transmiterea de segmente pana la umplerea intregii ferestre dupa care fie se primesc confirmari care vor permite unor noi pachete sa fie trimise, fie vor expira timer-ele de retransmisie si se va incepe retrimiterea pachetelor de la inceputul ferestrei. Din pacate un astfel de comportament poate duce la pomparea in retea a unui numar de pachete prea mare pentru capacitatea disponibila efectiv, inrautatind congestia. Pentru a evita acest lucru s-a propus urmatoarea solutie4: initial se trimite un segment; dupa primirea confirmarii lui se trimit doua segmente; dupa sosirea confirmarilor pentru ele se trimit patru segmente si asa mai departe. La un moment dat fie vor incepe sa se piarda segmente (un indiciu ca s-a atins capacitatea maxima a canalului) fie se va umple fereastra pe care o anunta cel care primeste. Trebuie sa remarcam ca datorita cresterii exponentiale a numarului de segmente se va atinge destul de repede una din cele doua situatii.
Modalitatea efectiva de implementare a acestui algoritm are la baza utilizarea unei ferestre de congestie (congestion window; cwnd) care este initializata cu dimensiunea unui segment (cwnd se calculeaza in octeti) si la fiecare pas este dublata; fereastra efectiva din cadrul careia se pot trimite segmente este data de minimul dintre ultima fereastra comunicata de partener si cwnd.
solutie4
Solutia apartine lui V. Jacobson si a fost prezentata in 1988 la conferinta ACM SIGCOMM-88
Deoarece TCP trebuie sa functioneze in conditii variate de latenta modul in care se face retransmiterea trebuie sa fie cat mai flexibil (si simplu in acelasi timp, pentru a introduce un overhead cat mai mic). Timpul cat se asteapta venirea unei confirmari (retransmission timeout RTO) este calculat prin cronometrarea timpului care ii ia unui segment trimis sa fie confirmat. Pentru o anumita conexiune se cronometreaza cate un singur segment la un moment dat iar pe baza RTT-ului masurat se actualizeaza valoare RTO-ului.
In RFC 793 formula de calcul a RTO-ului este urmatoarea:
unde este ultimul RTT masurat, este o estimare ponderata pentru RTT, este un coeficient de ponderare care in general are valoarea , iar este un coeficient cu o valoare recomandata de . Dupa cum se poate observa in valoarea lui este inclusa in mare masura vechea valoarea. In acest fel ajustarea RTT-ului se face treptat. Din pacate acest mod de calcul nu functioneaza bine la variatii mari ale RTT-ului, ducand la cresterea numarului de retransmisii exact atunci cand fenomenul de congestie incepe sa apara.
Pentru a remedia aceste neajunsuri V. Jacobsen a propus in 1988 o noua metoda de calcul, o metoda care tine seama seama si de modul in care variaza diferenta dintre RTT-uri. Formulele folosite sunt urmatoarele:
unde este un estimare pentru media RTT-urilor, este o estimare pentru abaterea RTT-urilor fata de medie (o aproximatie suficienta pentru abaterea patratica medie care insa este mult mai costisitor de calculat), este diferenta dintre RTT-ul masurat () si estimarea curenta (). Coeficientul cu care este actualizata estimarea curenta are valoarea de iar cel cu care este actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru si sunt alese astfel incat sa rezulte un RTT de secunde si un de 3 secunde (aceste recomandari sunt facute de RFC 1122).
Daca pentru un anumit segment nu se primeste confirmarea in intervalul indicat de el va fi retrimis si noul este dublat. Valoarea maxima admisa pentru este de 240 secunde. Deoarece in cazul retrimiterilor nu se poate determina cu exactitate caruia din segmentele trimise apartine confirmarea actualizarea estimarilor este amanata pana cand se reuseste trimiterea corecta (s-a primit confirmare) fara retransmitere(``din prima'') a unui segment. Acest artificiu (deloc neimportant) care permite evitarea actualizarea eronata a estimarilor este cunoscut sub numele de algoritmul lui Karn si a fost propus in 1987 de P. Karn si C. Partridge.
Daca cei doi parteneri care comunica prelucreaza datele suficient de repede si vor sa transfere un volum mare de date atunci limitarea de care se vor lovi este cea data de viteza retelei. Din cauza modului ``best-effort'' pe care IP-ul il ofera cand canalul de comunicatie este saturat o parte din segmentele TCP se vor pierde. In mod poate paradoxal atat transmitatorului cat si receptorul se pot afla in pozitia de a fi primii in detectarea pierderii unui segment. Unul din indiciile de la transmitator care semnaleaza pierderea unui segment este (in mod evident) aparitia unui timeout a timer-ului de retransmisie. La nivelul receptorului un indiciu al posibilei pierderi a unui segment este primirea unor segmente out-of-order. Deoarece TCP-ul in varianta initiala nu permite decat confirmari pozitive singurul lucru pe care receptorul il poate face este ca la fiecare segment out-of-order primit sa trimita o confirmare indicand prin aceasta ca la el continua sa vina segmente insa cel indicat de numarul de secventa de confirmare lipseste. Primirea acestor confirmari multiple este al doilea mod in care transmitatorul poate afla de aparitia congestiei.
Algoritmul ce trebuie aplicat in momentul in care se detecteaza aparitia congestiei este cunoscut sub numele de ``evitarea congestiei (congestion avoidence)''. Principiul care sta la baza lui este ca la aparitia congestiei fie sa se treaca la o incrementare liniara a dimensiunii ferestrei, daca congestia a fost detectata ca urmare a primirii unor confirmari identice repetate, fie sa se reia slow start-ul in cazul in care congestia s-a detectat prin expirarea unui timer de timeout. Implementarea acestui algoritm se bazeaza pe utilizarea unui nou contor (sstresh) care sa indice dimensiunea ferestrei de la care se trece de la incrementarea exponentiala la cea liniara. Algoritmul efectiv este urmatorul:
Dupa cum am vazut un receptor care primeste segmente out-of-order va trimite transmitatorului confirmari duplicate. Algoritmul denumit ``fast retransmission'' recomanda urmatoarele doua comportamenet:
Algoritmul de ``fast recovery'' incearca sa optimizeze si mai mult comportamentul transmitatorului care detecteaza un numar de trei sau mai multe confimari duplicate. Mai exact el recomanda trecerea la actualizarea liniara a ferestrei (congestion avoidance). Acest tip de comportament se poate justifica prin urmatorul rationament: deoarece inca mai sunt transferate date intre cei doi parteneri (si acest lucru se intampla sigur de vreme ce sosesc confirmari, duplicate in cazul acesta) inseamna ca transferul nu este afectat de o congestie severa si prin urmare trecerea la slow start nu e (inca) necesara (slow start-ul elibereaza aproape complet canalul deoarece cwnd este resetat la dimensiunea unui singur segment).
Cei doi algoritmi pot fi implementati in felul urmator:
Protocoalele bazate pe fereastra glisanta (cum este si TCP-ul) pot sa ajunga in situatia deloc fericita de trimite un numar mare de segmente mici in loc de segmente de dimensiune maxima. Acest tip de comportament este cunoscut sub numele de sindromul ``silly window''.
O modalitate prin care TCP-ul poate sa cada victima acestui tip de comportament este deschiderea de ferestre cu dimensiune foarte mica. O alta situatia nefericita este cea in care un transmitator este ``lacom'' si trimite date indiferent de cat de mica este fereastra (dupa cum vom vedea imediat uneori are sens si un astfel de comportament). Algoritmul de evitare a acestor neajunsuri este urmatorul:
Cateva justificari: cazul 2b trateaza cazul in care partenerul anunta ferestre mai mici decat dimensiunea unui segment iar cazul 2c impune conditiile respectarii algoritmului Nagle. dupa cum se vede daca algoritmul Nagle este activ si s-au acumulat destul date, mai exact cat dimensiunea unui segment, el va fi trimis chiar daca exista segmente neconfirmate. Pentru implementarea comportamentului impus de 2b un transmitator trebuie sa tina evidenta celei mai mari ferestre pe care partenerul a anuntat-o. Tinand seama ca dimensiunea acestor buffer-e nu se modifica acest mod de a incerca determinarea lor este suficient.
O alta problema legata tot de ferestre este cazul inchiderii acesteia. Un mod in care s-ar putea anunta redeschiderea este trimiterea de catre receptor a unei confirmari (duplicat) care sa anunte redeschiderea la o anumita valoare a ferestrei. Deoarece acest pachet nu trebuie confirmat in mod special si s-ar putea sa se piarda se poate ajunge in situatia in care receptorul a anuntat redeschiderea ferestrei, segmentul s-a pierdut iar transmitatorul inca mai il mai asteapta pentru a putea continua transferul. Rezolvarea la aceasta problema s-a facut prin impunerea unui alt comportament:
Observatie: timer-ul special necesar pentru implementare la transmitator a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer''. Numele este justificat de faptul ca sondarea deschiderii se va face pana cand fie fereastra se deschide, fie conexiunea se intrerupe.
Un lucru interesant despre TCP este faptul ca daca nivelele superioare nu comunica nimic intre ele pentru o perioada lunga atunci nici un segment nu se v-a transfera. Acest lucru este de fapt perfect rezonabil de vreme de TCP-ul este de fapt un fel de contract cu care cei doi parteneri au fost de acord din momentul in care au trecut cu succes de faza stabilirii legaturii. Daca nivelurile inferioare (retea/IP, fizic) devin temporar indisponibile cat tip cei doi nu vor sa comunice atunci acest lucru nu va perturba in nici un fel activitatea si acest lucru este acceptabil. Problemele incep sa apara in momentul in care cei doi doresc sa comunice si nivelele inferioare nu mai permit acest lucru. Evident ca cel care va dori sa comunice ceva va detecta intreruperea legaturii si va inchide conexiunea. Ce se intampla insa daca celalalt capat nu are nimic de comunicat (de exemplu este un server care ofera anumite servicii)? Pentru el legatura va fi in continuare activa si in general anumite resurse vor fi rezervate pentru aceasta. Rezolvarea acestei situatii este data de introducerea unei mecanism de sondare a starii legaturii pe baza unui timer (TCP Keepalive Timer) care se declanseaza din doua in doua ore. La fiecare expirare a timer-ului se trimite un segment fara date care confirma datele primite pana atunci. Raspunsul care trebuie primit este tot un segment fara date care confirma datele primite de partener (practic o re-publicare a starii celor doi parteneri). Daca raspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis. Daca dupa 10 astfel de incercari tot nu s-a primit nici un raspuns atunci conexiunea se va considera terminata si se va anunta nivelul superior asupra acestui lucru.
Observatii:
Subsections
Deoarece UDP-ul este un serviciu fara conexiune toate datele pe care le primeste de la nivelul superior sunt incapsulate intr-o singura datagrama UDP care apoi va forma un pachet IP. Daca pachetul IP astfel obtinut este prea mare atunci mecanismele IP de fragmentare il vor sparge in bucati. Exemplul urmator incearca sa studieze exact acest fenomen.
Pe masina athos
ruleaza un
server de UDP pe portul . Pe o alta
masina, frodo
, aflata in reteaua
locala este rulat un client care poate fi configurat sa trimita
un pachet UDP de o anumita lungime. Pentru a putea observa
ce se intampla pe athos
este rulat tcpdump
Deoarece MTU-ul pentru o retea Ethernet este in general 1500
si antetul IP plus cel UDP ocupa 20 + 8 = 28 octeti, o
datagrama UDP de dimensiune 1472 ar trebui sa fie trimisa
nefragmentata. Pentru siguranta, folosind clientul de pe athos
, s-a trimis
mai intai o datagrama UDP cu 1471 octeti de date, si apoi
inca una cu 1472. Pentru ambele tcpdump
a indicat
trimiterea lor fara fragmentare
La o dimensiune de 1473 ar trebui ca trimiterea sa genereze
doua pachete IP: unul care sa contina primii antetul UDP
plus primii 1472 octeti de date si inca un pachet IP care
contine un singur octet. Iata ce indica
tcpdump
-ul:
Intr-adevar au fost generate doua pachete IP:
more fragments
este resetat) dintr-o datagrama UDP (din antetul IP se poate
determina acest lucru) care a fost sparta in bucati;
deplasamentul octetului primit in datagrama originala este 1480; more fragments
este setat (acest lucru este indicat de semnul ``+'' de dupa
deplasament) Dupa cum se poate observa
ambele pachete poarta acelasi numar de identificare (36274).
Acest lucru impreuna cu informatiile date de flag-ul more fragments
permite reconstructia la destinatie a
datagramei UDP originale. O problema a acestui mod de fragmentare e
ca in cazul pierderii unui fragment intreaga datagrama va fi
compromisa si va trebui retrimisa in intregime.
Ce se va intampla daca vom incerca sa trimitem un datagrama UDP suficient de mare pentru a necesita spargerea in trei bucati? Iata mai jos un transfer de 2973 de octeti:
13:21:08.251495 frodo.noi > athos.noi: udp (frag 23522:1@2960) (ttl 64, len 21)Dupa cum se poate observa trimiterea in ordine inversa este o caracteristica a sistemului pe care am testat. O datagrama de dimesiune si mai mare (16273) confirma acest lucru:
13:21:52.266391 frodo.noi > athos.noi: udp (frag 23523:1@16280) (ttl 64, len 21)Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o
masina (frodo
) un server
de TCP care va asculta pe portul 50007, va accepta fiecare conexiune
primita si o va inchide imediat. Clientul va rula pe o alta
masina (alexandra
) si
dupa stabilirea conexiunii va inchide la randul sau conexiunea.
Desi acest lucru ar trebui sa duca la o inchidere simultana
in realitate vom vedea ca are loc o inchidere normala.
Iata ce arata un tcpdump
rulat pe alexandra
Liniile 1-2 reprezinta segmentul de SYN trimis de clientul de pe alexandra
.
Numarul de secventa este 2481641828, dimensiunea datelor
efective este 0, flag-ul de ACK nu este setat, dimensiunea ferestrei este de
5840 octeti (aceasta corespunde spatiului ocupat de 4 segmente TCP
continand fiecare 1460 octeti de date), dimensiunea maxima a
unui segment (MSS) este de 1460 octeti (aceasta dimensiune este
justificata de faptul ca intr-un frame Ethernet nu se pot trimite mai
mult de 1500 octeti si antetul IP + TCP ocupa 40 de
octeti). Alte informatii pe care acest prim segment le contine:
statia este capabila de a lucra cu notificari explicite
referitoare la congestie (prezenta flagurilor WE
indica
acest lucru; W
corespunde
flag-ului TCP Congestion Window Reduced iar E
ECN-Echo; ECN
este acronimul de sackOK
), cu
marcaje de timp (timestamp
) si
cu scalari de ferestre (wscale
Raspunsul (liniile 3-4) trimis de server-ul (frodo
)
confirma primirea segmentului (ack 2481641829
) de
deschidere de conexiune si isi publica si el
informatiile legate de fereastra, MSS, timestamp si scalari
ale dimensiunii ferestrei. In plus faptul ca flag-ul ECN-Echo nu este
setat (E
ar fi trebuit
sa apara langa S
) indica
faptul ca sistemul nu este capabil de ECN.
Liniile 5-6 reprezinta ultimul pas din secventa de
initializare: confirmarea de catre client a segmentului trimis de
server. Se poate observa ca de aici incolo tcpdump
-ul
afiseaza valori relative pentru numere de secventa si
cele de confirmare.
Mai departe (liniile 7-8) frodo
cere
inchiderea conxiunii (este setat flag-ul de FYN) prin trimiterea unui segment
care nu contine date dar are un nou numar de secventa (e
nevoie de asa ceva pentru ca partenerul sa poata confirma
primirea acestui segment). alexandra
raspunde (liniile 9-10) cu un segment care confirma primirea
segmentului de la frodo
si
anunta terminarea conexiunii si din capatul lui. Dupa ce alexandra
confirma primirea segmentului cele ambele statii considera
dialogul incheiat.
In conditii similare cu experimentul precedent vom incerca sa
observam modul in care are loc un transfer simplu de date. Serverul va
rula pe frodo
si se
va comporta ca un reflector: dupa stabilirea conexiunii asteapta
primirea unor date pe care apoi le trimite inapoi la
destinatie. Clientul va rula pe alexandra
si
dupa stabiliea conexiunii va trimite 8 octeti de date, va
astepta raspunsul si apoi va inchide conexiunea.
Un tcpdump
rulat pe alexandra
arata urmatoarele:
Primele trei segmente (liniile 1-6) reprezinta o deshidere identica cu cea pe care am studiat-o in cazul precedent. Segmentul care apare pe liniile 7-8 reprezinta cei 8 octeti de date care se doreau transferati. Deoarece segmentul contine toate datele flagul de PUSH este activat. Dupa ce datele au fost receptionate la server acesta genereaza un segment fara date (liniile 9-10) si apoi le trimite inapoi (liniile 10-11). Clientul care le primeste raspunde cu un segment de confirmare (liniile 13-14 Mai departe urmeaza o inchidere similara cu cea din exemplu precedent(liniile 15-20).
O observatie care se poate face pe baza afisarii
furnizate de tcpdump
e ca
mecanismul de intarziere a confirmarilor nu a fost activ. Daca ar fi
fost activ atunci confirmarea din segmentul de pe liniile 13-14 ar fi trebui
sa faca parte din segmentul de date care urmeaza imediat
(liniile 15-16). O posibila explicatie e ca frodo
e inca
in portiunea de slow start in care nici o confirmare nu e
intarziata pentru a deschide cat mai repede fereastra de congestie.
Politica de confidentialitate | Termeni si conditii de utilizare |
Vizualizari: 1955
Importanta:
Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved