Scrigroup - Documente si articole

     

HomeDocumenteUploadResurseAlte limbi doc
AccessAdobe photoshopAlgoritmiAutocadBaze de dateCC sharp
CalculatoareCorel drawDot netExcelFox proFrontpageHardware
HtmlInternetJavaLinuxMatlabMs dosPascal
PhpPower pointRetele calculatoareSqlTutorialsWebdesignWindows
WordXml


Protocoale TCP/IP - UDP, TCP

retele calculatoare



+ Font mai mare | - Font mai mic



  • Protocoale TCP/IP la nivelul transport
    • 1 UDP
      • A. Caracteristici UDP
      • B. Formatul pachetelor UDP
    • 2 TCP
      • A. Caracteristici TCP
      • B. Formatul pachetelor TCP
      • C. Initierea si terminarea unei conexiuni TCP
        • Protocolul de initiere
        • Protocolul de terminare
        • Diagrama de stari
      • D. Controlul fluxului
        • Intarzierea confirmarilor
        • Algoritmul Nagle
        • Fereastra glisanta
        • Slow start
        • Retransmission Timeout (RTO) si Round-Trip Time (RTT)
        • Evitarea congestiei
        • Fast Retransmission, Fast Recovery
        • Sindromul ``Silly Window''
        • TCP Keepalive Timer
    • 3 Studii de caz
      • A. Fragmentarea pachetelor UDP
      • B. Stabilirea si eliberarea unei conexiuni TCP
      • C. Transferul de date TCP


1 UDP

Subsections

  • A. Caracteristici UDP
  • B. Formatul pachetelor UDP

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:

  • este un serviciu de tip datagrama: cererile de trimitere de date primite de la nivelul superior sunt tratate independent;
  • comunicarea are loc fara stabilirea unei legaturi (conection-less): nu exista mecanisme de stabilire si terminare a unei conexiuni deoarece toate datele sunt trimise in cadrul unui singur pachet IP, care eventual va fi supus fragmentarii;
  • nu se garanteaza ajungerea ala destinatie a datelor (best effort): ajungerea la destinatie nu este anuntata sursei;
  • datele transportate sunt protejate de o suma de control (introdusa ca optionala initial ea este trecuta ca necesara(must) in RFC 1122 care stabileste modul de comportare al clientilor in Internet);
  • overhead-ul introdus este minim: doar 8 octeti.

Cateva utilizari tipice ale UDP-ului:

  • servicii de rezolvare a numelor (DNS): deoarece intrebarile si raspunsurile scurte pot fi mai eficient implementate peste UDP;
  • fluxuri multimedia: deoarece mecanismele complicate de control al fluxului ale TCP-ului ar deprecia interactivitatea;
  • server de fisiere (NFS): deoarece acest tip de aplicatii sunt in general rulate in retele locale cu performante ridicate care nu necesita mecanismele TCP;
  • managementul retelei (SNMP);
  • protocoale de rutare (RIP).

Footnotes

RFC 768 are nici mai mult nici mai putin decat 3 pagini; nu contine cuprins dar are o lista de 5 referinte bibliografice

B. Formatul pachetelor UDP

Datagramele UDP sunt formate dintr-un antet (figura 7.1) urmat de datele care se doresc transmise (daca exista).

Figura 7.1: Structura unei datagrame UDP

Antetul cuprinde:

  • port sursa - 16 biti;

Impreuna cu adresa IP a sursei acest numar identifica in mod unic locul de unde a fost trimis datagrama UDP;

  • port destinatie - 16 biti

Impreuna cu adresa IP a destinatiei acest numar identifica in mod unic destinatia dorita pentru datagrama UDP;

  • lungimea pachetului UDP - 16 biti

Lungimea minima masoara datagrama UDP cu tot cu antent si prin urmare are o valoare minima de 8 octeti.

  • suma de control - 16 biti;

Suma de control acopera intreg pachetul UDP cat si un pseudo antet de 12 octeti format din:

  • adresa IP a sursei - 32 biti;
    • adresa IP a destinatiei - 32 biti;
      • 8 biti de zero pentru aliniere;
      • numarul protocolului UDP (17) reprezentat pe 8 biti;
      • lungimea pachetului UDP - 16 biti

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.

2 TCP

Subsections

  • A. Caracteristici TCP
  • B. Formatul pachetelor TCP
  • C. Initierea si terminarea unei conexiuni TCP
    • Protocolul de initiere
      • 1 Deschiderea simultana
    • Protocolul de terminare
      • 2 Terminarea simultana
      • 3 Resetarea conexiunii
    • Diagrama de stari
  • D. Controlul fluxului
    • Intarzierea confirmarilor
    • Algoritmul Nagle
    • Fereastra glisanta
    • Slow start
    • Retransmission Timeout (RTO) si Round-Trip Time (RTT)
    • Evitarea congestiei
    • Fast Retransmission, Fast Recovery
    • Sindromul ``Silly Window''
    • TCP Keepalive Timer

A. Caracteristici TCP

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 1989 a RFC-ului cu numarul 2581. In el se specifica foarte strict comportamentul care este permis pentru o implementare de TCP. Alaturi de protocolul UDP, TCP se situeaza pe nivelul transport in ierarhia de protocoale, deci intre nivelul aplicatie si nivelul retea. Dar, cu toate ca se bazeaza pe acelasi protocol (IP) ca si UDP, TCP furnizeaza catre nivelul aplicatie cu totul alt tip de servicii, servicii orientate-conexiune, sigure, de tip flux de octeti. Termenul de orientat-conexiune presupune ca, intre cele doua aplicatii care comunica utilizand TCP, trebuie sa se stabileasca o conexiune TCP inainte ca transferul de date sa aiba loc. Aceasta conexiune nu este efectiv una fizica ci virtuala, asemanator cum se intampla in sistemul de telefonie clasica: cineva formeaza un numar si abia in momentul in care cealalta persoana raspunde se poate incepe conversatia. Fiind o conexiune host-la-host, nu exista notiunile de broadcast sau multicast.

Transferul sigur de date este asigurat in urmatorul mod:

  • Datele sunt impartite in bucati a caror dimensiune optima e determinata de TCP, spre deosebire de UDP care trimite datagrame UDP corespunzatoare cu dimensiunea datelor primite de la nivelul aplicatie. Unitatea de date trimisa de TCP catre nivelul retea poarta numele de segment.
  • Cand TCP trimite un segment porneste un timer si daca nu se primeste confirmarea segmentului respectiv intr-un anumit timp, il retransmite.
  • In momentul in care se primeste un segment TCP trimite o confirmare (din motive de eficienta aceasta poate fi amanata un anumit interval de timp).
  • In headerul TCP este mentinuta o suma de control pentru detectarea modificarilor in date. Daca se receptioneaza un segment corupt TCP il ignora urmand sa fie retransmis datorita neprimirii confirmarii.
  • Deoarece segmentele TCP sunt transmise mai departe incapsulate in datagrame IP iar acestea pot ajunge in orice ordine, segmentele TCP pot ajunge in alta ordine decat cea in care au fost trimise. De aceea, la destinatie TCP-ul trebuie sa se foloseasca de numere de secventa pentru a reordona eventual segmentele inainte de a le livra catre nivelul aplicatie. De asemenea, TCP trebuie sa asigure ignorarea duplicatelor.
  • TCP asigura controlul fluxului in conditiile in care viteza de trimitere a datelor de la sursa poate fi mult prea mare decat capacitatea de prelucrare de la destinatie.

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.

B. Formatul pachetelor TCP

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.

Figura 7.2: Structura unui segment TCP

Antetul unui segment TCP cuprinde:

  • port sursa - 16 biti pentru specificarea portului aplicatiei transmitatoare
  • port destinatie - 16 biti pentru specificarea portului aplicatiei ce receptioneaza segmentul TCP

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).

  • numar de secventa - 32 biti

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.

  • confirmare - 32 biti

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.

  • lungimea antetului - 4 biti

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).

  • 6 biti rezervati pentru utilizari viitoare
  • 6 biti de control reprezentand urmatoarele flag-uri ce pot fi setate simultan:
    • URG - campul urgent pointer este valid
    • ACK - campul de confirmare este valid
    • PSH - destinatia trebuie sa trimita datele catre nivelul aplicatie cat mai devreme
    • RST - se doreste resetarea conexiunii
    • SYN - initierea conexiunii
    • FIN - inchiderea conexiunii
  • dimensiunea ferestrei - 16 biti

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.

  • suma de control - 16 biti

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.

  • urgent pointer - 16 biti

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.

  • optiuni - pana la 40 de octeti (figura 7.3)

Cele mai utilizate optiuni sunt:

    • Sfarsit de optiuni (end of option) - 1 octet

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.

    • no operation - 1 octet

Utilizat pentru alinierea la cuvinte de 32 de biti.

    • Dimensiunea maxima a segmentului (Maximum Segment Size (MSS)) - 16 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).

    • Factor de scalare a ferestrei (Window scale factor) - 1 octet

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.

    • Timestamp - 10 octeti

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.

Figura: Optiuni TCP

C. Initierea si terminarea unei conexiuni TCP

TCP este un protocol orientat conexiune, deci presupune stabilirea unei cai virtuale intre sursa si destinatie.

Subsections

  • C.1Protocolul de initiere
    • C.1 Deschiderea simultana
  • C.2Protocolul de terminare
    • C.2.1 Terminarea simultana
    • C.2.2 Resetarea conexiunii
  • C.3Diagrama de stari

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:

  1. Clientul trimite un segment cu flag-ul SYN setat si care contine portul sursa, portul de la destinatie si numarul de secventa generat initial (ISN) de la care se vor numerota octetii de la client catre server. Optional se pot stabili parametrii conexiunii prin setarea lungimii maxime a segmentelor (MSS) dispus sa le primeasca de la server, factorului de scalare a ferestrei. Acest prim segment nu contine nici un parametru de confirmare si de asemenea nu are rost sa contine sa seteze dimensiunea ferestrei.
  2. Al doilea segment e trimis de server si are un rol dublu: confirma segmentul primit de la client prin setarea flag-ului ACK si completeaza numarul de secventa cu numarul de secventa primit plus 1 si, al doilea rol, initializeaza conexiunea de la el catre client prin setarea flag-ului SYN si generarea unui numar de secventa initial ce va fi folosit in numerotarea octetilor de la server spre client. Pe langa aceasta trebuie sa contina dimensiunea ferestrei si optional, poate seta factorul de scalare si dimensiunea maxima a segmentului acceptat.
  3. Clientul trimite un segment cu confirmarea cererii din partea serverului (ACK setat + completeaza numarul confirmat cu numarul de secventa primit + 1). Ca si in cazul pasului 2, trebuie sa seteze dimensiunea ferestrei. Acest pachet poate contine date.

C.1.1 Deschiderea simultana

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.

C.2 Protocolul de terminare

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:

  1. Clientul trimite un segment cu flag-ul FIN activat, solicitand inchiderea conexiunii.
  2. Serverul trimite un segment ACK confirmand primirea cererea. Numarul de confirmare se completeaza normal, ca numarul de secventa primit + 1
  3. Serverul continua sa trimita date catre client si cand doreste sa inchida si el conexiunea trimite un segment cu FIN activat.
  4. Clientul trimite un pachet ACK confirmand inchiderea conexiunii.

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

  • C.2.1 Terminarea simultana
  • C.2.2 Resetarea conexiunii

C.2.1 Terminarea simultana

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.

C.2.2 Resetarea conexiunii

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).

C.3 Diagrama de stari

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

Stare

Descriere

CLOSED

Nu exista conexiune.

LISTEN

Serverul asteapta cereri de la clienti.

SYN_SENT

Cerere de initiere (activa) a conexiunii. Se asteapta confirmarea.

SYN_RCVD

S-a primit o cerere de initiere conexiune.

ESTABLISHED

S-a stabilit conexiunea.

FIN_WAIT_1

Aplicatia a solicitat inchiderea conexiunii.

FIN_WAIT_2

Serverul a acceptat inchiderea conexiunii.

CLOSING

Ambele parti solicita simultan inchiderea conexiunii.

TIME_WAIT

Conexiune inchisa dar se asteapta ca pachetele retransmise sa dispara.

CLOSE_WAIT

Serverul asteapta inchiderea dinspre partea aplicatiei.

LAST_ACK

Serverul a inchis conexiunea. Asteapta ultima confirmare.

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:

  • Initial clientul TCP se afla in starea CLOSED.
  • Asteptand in starea CLOSED clientul poate primi de la aplicatie o cerere de initiere activa a unei conexiuni. Trimite un segment SYN si trece in starea SYN_SENT.
  • In starea SYN_SENT clientul asteapta de la server un segment ACK+SYN, dupa care trimite un ACK si trece in starea ESTABLISHED. Din acest moment poate incepe transferul efectiv de date. Clientul va ramane in aceasta stare cat timp are de trimis/primit date.
  • Aflat in aceasta stare clientul TCP poate primi din partea aplicatiei o cerere de inchidere a conexiunii. In acest caz va trimit un segment FIN si trece in starea FIN_WAIT_1.
  • In aceasta stare clientul asteapta ACK din partea serverului. Dupa ce-l primeste conexiunea intr-un sens se va inchide si clientul trece in starea FIN_WAIT_2.
  • Starea FIN_WAIT_2 dureaza pana cand primeste cererea de inchidere a conexiunii, FIN, din partea serverului. Trimite ACK si va trece in starea TIME_WAIT.
  • In aceasta stare se va porni un timer cu valoarea setata la dublul timpului de viata estimat pentru un segment de lungime maxima, MSL (Maximum Segment Lifetime). Acest timer permite retransmiterea ACK-ului in cazul in care acesta se pierde (celalalt capat va da timeout si va retransmite segmentul FIN). In tot acest time cei doi socketi (de la client si server) nu vor putea fi reutilizati. Totodata pachetele intarziate care sosesc in aceasta perioada sunt ignorate. Dupa expirarea acestui timer clientul revine in starea initiala CLOSED.

Din punctul de vedere al unui server o comportare standard parcurge urmatoarele stari: CLOSED, LISTEN, SYN_RCVD, ESTABLISHED, CLOSE_WAIT si LAST_ACK:

  • Initial serverul TCP se afla in starea CLOSED.
  • In aceasta stare poate primi de la aplicatia server o cerere de initiere activa si trece in starea LISTEN.
  • Aflat in starea LISTEN serverului TCP poate receptiona un segment SYN de la un client TCP. In acest caz va trimite ACK+SYN si va trece in starea SYN_RCVD.
  • In aceasta stare serverul asteapta primirea confirmarii de la client, moment in care conexiunea e stabilita in ambele sensuri si se poate incepe transferul de date (starea ESTABLISHED).
  • Clientul TCP poate solicita inchiderea conexiunii trimitand un segment FIN catre server. In acest caz serverul TCP trimite confirmarea si trece in starea CLOSE_WAIT.
  • In aceasta stare serverul asteapta sa primeasca din partea programului server inchiderea conexiunii, moment in care va trimite catre client un segment FIN si trece in starea LAST_ACK.
  • Serverul asteapta primirea ultimei confirmari de la client dupa care revine in starea CLOSED.

Atat serverul cat si clientul TCP se pot afla in oricare din cele 11 stari ale diagramei.

Figura: Diagrama de stari pentru TCP

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

  • Intarzierea confirmarilor
  • Algoritmul Nagle
  • Fereastra glisanta
  • Slow start
  • Retransmission Timeout (RTO) si Round-Trip Time (RTT)
  • Evitarea congestiei
  • Fast Retransmission, Fast Recovery
  • Sindromul ``Silly Window''
  • TCP Keepalive Timer

Intarzierea confirmarilor

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.

Footnotes

Acest comportament a fost propus de David D. Clark in iulie 1982 in RFC 813

Algoritmul Nagle

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

Footnotes

algoritm3

Algoritmul apartinand lui John Nagle a fost propus in ianuarie 1984 in RFC 896

Fereastra glisanta

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:

  1. pachete trimis si pentru care s-a primit confirmare
  2. pachete trimise si pentru care se asteapta inca confirmarea
  3. pachete care nu au fost trimise inca dar care nu depasesc limitele ferestrei si deci pot fi trimise
  4. pachete care inca nu au fost trimite si care nici nu vor putea fi trimise decat dupa ce au fost trimise toate pachetele din categoria 3 si s-au primit o parte din confirmarile la pachetele din categoria 2

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.

Slow start

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.

Footnotes

solutie4

Solutia apartine lui V. Jacobson si a fost prezentata in 1988 la conferinta ACM SIGCOMM-88

Retransmission Timeout (RTO) si Round-Trip Time (RTT)

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.

Evitarea congestiei

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:

  1. la stabilirea unei noi conexiuni se pleaca cu sstresh initializat la valoare de 64K si cwnd la dimensiunea unui segment
  2. trimiterea de segmente se face fara a depasi minimul dintre fereastra publicata de partener (pentru a nu depasi capacitatea de procesesare a partenerului) si cwnd-ul curent (pentru a nu depasi limita impusa de capacitatea retelei)
  3. la aparitia congestiei sstresh este setat la jumatatea valorii ferestrei curente (minimul dintre fereastra anuntata de partener si cwnd insa cel putin dimensiunea corespunzatoare pentru doua segmente); daca congestia a fost detectata prin expirarea unui timer de timeout atunci cwnd este initializat cu dimensiunea unui segment
  4. la primirea unei confirmari incrementarea se face in doua moduri, in functie de relatie in care se afla cwnd si sstresh:
    1. daca cwnd e mai mic sau egal cu sstresh se face incrementarea exponentiala caracteristica slow start-ului (care de fapt nu e deloc slow in cazul de fata)
    2. daca cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea unui segment

Fast Retransmission, Fast Recovery

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:

  1. un receptor care detecteaza segmente out-of order trebuie sa nu intarzie trimiterea de confirmari (dupa cum am vazut in general confimarile sunt intarziate micsora numarul de pachete fara date care sunt transferate)
  2. un transmitator care care primeste mai mult de trei confirmari duplicate trebuie sa retrimita segmentul indicat ca fiind neprimit de confirmarile in cauza fara a astepta expirarea timer-ul de timeout

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:

  1. cand se detecteaza trei confirmari consecutive identice se seteaza sstresh la jumatate din valoarea cwnd; se retransmite segmentul care s-a pierdut si se seteaza cwnd la valoarea egala cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de incrementare a cwnd sa treaca la incrementare liniara)
  2. la fiecare confirmare duplicata care mai soseste se incrementeaza cwnd se incrementeaza cu dimensiunea unui segment
  3. cand inceteaza primirea de confirmari duplicate (segmentul retrimis a ajuns cu bine la receptor si s-a trimis o confirmare care acopera segmentul care se pierduse initial) cwnd este setat la valoarea sstresh

Sindromul ``Silly Window''

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:

  1. un receptor nu trebuie sa anunte deschideri de ferestre mici. Mai exact nu se recomanda anuntarea unei incrementari a ferestrei mai mica decat dimensiunea unui segment (MSS) sau jumatate din buffer-ul aflat la dispozitia receptorului, oricare din ele e mai mica.
  2. un transmitator va trimite date doar in urmatoarele cazuri:
    1. se poate trimite un segment intreg
    2. se poate trimite jumatate din dimensiunea celei mai mari ferestre pe care partenerul a publicat-o pana acum
    3. toate datele trimise pana acum au fost confirmate sau algoritmul Nagle este dezactivat si se trimit toate datele care sunt in buffer-ul de trimitere

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:

  1. transmitatorul va trimite segmente cu dimensiunea datelor de un octet prin care sondeaza deschiderea ferestrei; intervalul la care se sondeaza redeschiderea ferestrei se dubleaza (exponential backoff); in RFC 793 dimensiunea maxima recomandata este de 2 minute insa in RFC 1122 se specifica ca maximul este acelasi cu cel din cazul retransmisiei (240 secunde)
  2. receptorul trebuie sa refuze aceste pachete raspunzand cu segmente de confirmare care indica neprimirea octetului respectiv

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.

TCP Keepalive Timer

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:

  • daca o statie primeste segmente de keepalive despre conexiuni care nu mai sunt active (de exemplu a fost resetat) atunci va raspunde cu segmente de reset (acesta e un procedeu standard);
  • RFC 1122 specifica ca facilitatea de keepalive trebuie activata in mod explicit.

3 Studii de caz

Subsections

  • A. Fragmentarea pachetelor UDP
  • B. Stabilirea si eliberarea unei conexiuni TCP
  • C. Transferul de date TCP

1 Fragmentarea pachetelor UDP

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

18:25:56.721144 frodo.noi.33274 > athos.noi.50007: udp 1471 (DF) (ttl 64, id 51481, len 1499)
18:25:59.846764 frodo.noi.33274 > athos.noi.50007: udp 1472 (DF) (ttl 64, id 51793, len 1500)

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:

18:26:05.705813 frodo.noi > athos.noi: udp (frag 36274:1@1480) (ttl 64, len 21)
18:26:05.706116 frodo.noi.33274 > athos.noi.50007: udp 1473 (frag 36274:1480@0+) (ttl 64, len 1500)

Intr-adevar au fost generate doua pachete IP:

  • primul contine doar un singur octet de date si reprezinta ultimul fragment (bitul de 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;
  • al doilea pachet este primul fragment din datagrama UDP si contine antetul UDP (din cauza asta datele efective ocupa doar 1480 octeti); deplasamentul este 0 si bitul de 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)
13:21:08.251795 frodo.noi > athos.noi: udp (frag 23522:1480@1480+) (ttl 64, len 1500)
13:21:08.251935 frodo.noi.32843 > athos.noi.50007: udp 2953 (frag 23522:1480@0+) (ttl 64, len 1500)

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)
13:21:52.266697 frodo.noi > athos.noi: udp (frag 23523:1480@14800+) (ttl 64, len 1500)
13:21:52.266843 frodo.noi > athos.noi: udp (frag 23523:1480@13320+) (ttl 64, len 1500)
13:21:52.266976 frodo.noi > athos.noi: udp (frag 23523:1480@11840+) (ttl 64, len 1500)
13:21:52.267114 frodo.noi > athos.noi: udp (frag 23523:1480@10360+) (ttl 64, len 1500)
13:21:52.267253 frodo.noi > athos.noi: udp (frag 23523:1480@8880+) (ttl 64, len 1500)
13:21:52.267391 frodo.noi > athos.noi: udp (frag 23523:1480@7400+) (ttl 64, len 1500)
13:21:52.267539 frodo.noi > athos.noi: udp (frag 23523:1480@5920+) (ttl 64, len 1500)
13:21:52.267678 frodo.noi > athos.noi: udp (frag 23523:1480@4440+) (ttl 64, len 1500)
13:21:52.267819 frodo.noi > athos.noi: udp (frag 23523:1480@2960+) (ttl 64, len 1500)
13:21:52.267956 frodo.noi > athos.noi: udp (frag 23523:1480@1480+) (ttl 64, len 1500)
13:21:52.268096 frodo.noi.32843 > athos.noi.50007: udp 16273 (frag 23523:1480@0+) (ttl 64, len 1500)

2 Stabilirea si eliberarea unei conexiuni TCP

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

[numbers=left]
22:46:47.558868 alexandra.noi.34437 > frodo.noi.50007: SWE 2481641828:2481641828(0)
win 5840 <mss 1460,sackOK,timestamp 10422756 0,nop,wscale 0> (DF)
22:46:47.559023 frodo.noi.50007 > alexandra.noi.34437: S 1579802286:1579802286(0) ack 2481641829
win 5792 <mss 1460,sackOK,timestamp 9639913 10422756,nop,wscale 0> (DF)
22:46:47.559081 alexandra.noi.34437 > frodo.noi.50007: . ack 1
win 5840 <nop,nop,timestamp 10422756 9639913> (DF)
22:46:47.559435 frodo.noi.50007 > alexandra.noi.34437: F 1:1(0) ack 1
win 5792 <nop,nop,timestamp 9639913 10422756> (DF)
22:46:47.560243 alexandra.noi.34437 > frodo.noi.50007: F 1:1(0) ack 2
win 5840 <nop,nop,timestamp 10422756 9639913> (DF)
22:46:47.560332 frodo.noi.50007 > alexandra.noi.34437: . ack 2
win 5792 <nop,nop,timestamp 9639913 10422756> (DF)

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 la Explicit Congestion Notification), cu confirmari selective (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.

3 Transferul de date TCP

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:

[numbers=left]
21:09:47.449182 alexandra.noi.35455 > frodo.noi.50007: SWE 3531138850:3531138850(0)
win 5840 <mss 1460,sackOK,timestamp 14016045 0,nop,wscale 0> (DF)
21:09:47.449326 frodo.noi.50007 > alexandra.noi.35455: S 2833284198:2833284198(0) ack 3531138851
win 5792 <mss 1460,sackOK,timestamp 13950430 14016045,nop,wscale 0> (DF)
21:09:47.449374 alexandra.noi.35455 > frodo.noi.50007: . ack 1
win 5840 <nop,nop,timestamp 14016045 13950430> (DF)
21:09:47.449924 alexandra.noi.35455 > frodo.noi.50007: P 1:9(8) ack 1
win 5840 <nop,nop,timestamp 14016045 13950430> (DF)
21:09:47.450025 frodo.noi.50007 > alexandra.noi.35455: . ack 9
win 5792 <nop,nop,timestamp 13950430 14016045> (DF)
21:09:47.450145 frodo.noi.50007 > alexandra.noi.35455: P 1:9(8) ack 9
win 5792 <nop,nop,timestamp 13950430 14016045> (DF)
21:09:47.450161 alexandra.noi.35455 > frodo.noi.50007: . ack 9
win 5840 <nop,nop,timestamp 14016045 13950430> (DF)
21:09:47.450487 alexandra.noi.35455 > frodo.noi.50007: F 9:9(0) ack 9
win 5840 <nop,nop,timestamp 14016045 13950430> (DF)
21:09:47.450660 frodo.noi.50007 > alexandra.noi.35455: F 9:9(0) ack 10
win 5792 <nop,nop,timestamp 13950431 14016045> (DF)
21:09:47.450691 alexandra.noi.35455 > frodo.noi.50007: . ack 10
win 5840 <nop,nop,timestamp 14016045 13950431> (DF)

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



DISTRIBUIE DOCUMENTUL

Comentarii


Vizualizari: 1955
Importanta: rank

Comenteaza documentul:

Te rugam sa te autentifici sau sa iti faci cont pentru a putea comenta

Creaza cont nou

Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved