Reţele locale de calculatoare
Ghid de laborator
Cuprins
7 Protocoale TCPIP la nivelul transport
o 1 UDP
1 Caracteristici UDP
2 Formatul pachetelor UDP
o 2 TCP
1 Caracteristici TCP
2 Formatul pachetelor TCP
3 Iniţierea şi terminarea unei conexiuni TCP
Protocolul de iniţiere
Protocolul de terminare
Diagrama de stări
4 Controlul fluxului
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
o 3 Studii de caz
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
Bibliografie
About this document
Cuprins
7 Protocoale TCPIP la nivelul transport
o 1 UDP
1 Caracteristici UDP
2 Formatul pachetelor UDP
o 2 TCP
1 Caracteristici TCP
2 Formatul pachetelor TCP
3 Iniţierea şi terminarea unei conexiuni TCP
4 Controlul fluxului
o 3 Studii de caz
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
Bibliografie
About this document
7 Protocoale TCPIP la nivelul transport
Subsections
1 UDP
o 1 Caracteristici UDP
o 2 Formatul pachetelor UDP
2 TCP
o 1 Caracteristici TCP
o 2 Formatul pachetelor TCP
o 3 Iniţierea şi terminarea unei conexiuni TCP
Protocolul de iniţiere
1 Deschiderea simultană
Protocolul de terminare
2 Terminarea simultană
3 Resetarea conexiunii
Diagrama de stări
o 4 Controlul fluxului
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
3 Studii de caz
o 1 Fragmentarea pachetelor UDP
o 2 Stabilirea şi eliberarea unei conexiuni TCP
o 3 Transferul de date TCP
1 UDP
Subsections
1 Caracteristici UDP
2 Formatul pachetelor UDP
1 Caracteristici UDP
UDP (User Datagram Protocol) este un protocol de nivel transport construit special pentru a oferi
un serviciu de comunicare cacirct mai simplu peste IP Specificaţiile protocolului au fost publicate icircn
1980 icircn RFC-ul cu numărul 7681
Cacircteva caracteristici ale UDP-ului sunt
este un serviciu de tip datagramă cererile de trimitere de date primite de la nivelul
superior sunt tratate independent
comunicarea are loc fără stabilirea unei legături (conection-less) nu există mecanisme de
stabilire şi terminare a unei conexiuni deoarece toate datele sunt trimise icircn cadrul unui
singur pachet IP care eventual va fi supus fragmentării
nu se garantează ajungerea ala destinaţie a datelor (best effort) ajungerea la destinaţie nu
este anunţată sursei
datele transportate sunt protejate de o sumă de control (introdusă ca opţională iniţial ea
este trecută ca necesară(must) icircn RFC 1122 care stabileşte modul de comportare al
clienţilor icircn Internet)
overhead-ul introdus este minim doar 8 octeţi
Cacircteva utilizări tipice ale UDP-ului
servicii de rezolvare a numelor (DNS) deoarece icircntrebările şi răspunsurile 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 fişiere (NFS) deoarece acest tip de aplicaţii sunt icircn general rulate icircn reţele
locale cu performanţe ridicate care nu necesită mecanismele TCP
managementul reţelei (SNMP)
protocoale de rutare (RIP)
Footnotes
7681
RFC 768 are nici mai mult nici mai puţin decacirct 3 pagini nu conţine cuprins dar are o listă
de 5 referinţe bibliografice
2 Formatul pachetelor UDP
Datagramele UDP sunt formate dintr-un antet (figura 71) urmat de datele care se doresc
transmise (dacă există)
Figura 71 Structura unei datagrame UDP
Antetul cuprinde
port sursă - 16 biţi
Icircmpreună cu adresa IP a sursei acest număr identifică icircn mod unic locul de unde a fost
trimis datagrama UDP
port destinaţie - 16 biţi
Icircmpreună cu adresa IP a destinaţiei acest număr identifică icircn mod unic destinaţia dorită
pentru datagrama UDP
lungimea pachetului UDP - 16 biţi
Lungimea minimă măsoară datagrama UDP cu tot cu antent şi prin urmare are o valoare
minimă de 8 octeţi
sumă de control - 16 biţi
Suma de control acoperă icircntreg pachetul UDP cacirct şi un pseudo antet de 12 octeţi format
din
adresa IP a sursei - 32 biţi
o adresa IP a destinaţiei - 32 biţi
8 biţi de zero pentru aliniere
numărul protocolului UDP (17) reprezentat pe 8 biţi
lungimea pachetului UDP - 16 biţi
Deoarece suma de control necesită icircn calculul ei un număr multiplu de 16 octeţi la
sfacircrşitul datelor se adaugă un număr potrivit de octeţi de zero Dacă suma este 0 atunci ea
va fi stocată ca 65535 (toţi biţii pe 1) Un 0 icircn cacircmpul de sumei de control indică faptul
că suma de control nu a fost calculată Observaţie chiar dacă un client are inhibat (icircn
mod explicit) calcului sumei de control el este obligat să verifice suma pachetelor care
sosesc şi au suma calculată
2 TCP
Subsections
1 Caracteristici TCP
2 Formatul pachetelor TCP
3 Iniţierea şi terminarea unei conexiuni TCP
o Protocolul de iniţiere
1 Deschiderea simultană
o Protocolul de terminare
2 Terminarea simultană
3 Resetarea conexiunii
o Diagrama de stări
4 Controlul fluxului
o Icircntacircrzierea confirmărilor
o Algoritmul Nagle
o Fereastra glisantă
o Slow start
o Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
o Evitarea congestiei
o Fast Retransmission Fast Recovery
o Sindromul ``Silly Window
o TCP Keepalive Timer
1 Caracteristici TCP
Deoarece protocolul IP este de tip datagramă utilizarea lui direct icircn aplicaţii care in general au
nevoie de conexiuni sigure este mult prea anevoioasă Din aceste motive peste IP a fost construit
un alt protocol TCP (transimission control protocol) care corectează aceste probleme Prima
definire se găseşte icircn RFC-ul cu numărul 793 şi datează din septembrie 1981 Din cauza deselor
congestii apărute icircn 1986 algoritmul care stă la baza TCP-ului este reanalizat şi icircn octombrie
1989 icircn RFC-ul cu numărul 1122 este publicată o nouă specificare mult mai eficientă şi
neambiguă a TCP-ului Noi probleme legate de viteze mari sunt tratate icircn RFC-ul 1323 iar icircn
2018 TCP-ul este extins pentru a permite confirmările selective (selective acknowledge) Seria
de RFC-urie fundamentale este icircncheiată de apariţia icircn 1989 a RFC-ului cu numărul 2581 Icircn el
se specifică foarte strict comportamentul care este permis pentru o implementare de TCP
Alături de protocolul UDP TCP se situează pe nivelul transport icircn ierarhia de protocoale deci
icircntre nivelul aplicaţie şi nivelul reţea Dar cu toate că se bazează pe acelaşi protocol (IP) ca şi
UDP TCP furnizează către nivelul aplicaţie cu totul alt tip de servicii servicii orientate-
conexiune sigure de tip flux de octeţi
Termenul de orientat-conexiune presupune că icircntre cele două aplicaţii care comunică utilizacircnd
TCP trebuie să se stabilească o conexiune TCP icircnainte ca transferul de date să aibă loc Această
conexiune nu este efectiv una fizică ci virtuală asemănător cum se icircntacircmplă icircn sistemul de
telefonie clasică cineva formează un număr şi abia icircn momentul icircn care cealaltă persoană
răspunde se poate icircncepe conversaţia Fiind o conexiune host-la-host nu există noţiunile de
broadcast sau multicast
Transferul sigur de date este asigurat icircn următorul mod
Datele sunt icircmpărţite icircn bucăţi a căror dimensiune optimă e determinată de TCP spre
deosebire de UDP care trimite datagrame UDP corespunzătoare cu dimensiunea datelor
primite de la nivelul aplicaţie Unitatea de date trimisă de TCP către nivelul reţea poartă
numele de segment
Cacircnd TCP trimite un segment porneşte un timer şi dacă nu se primeşte confirmarea
segmentului respectiv icircntr-un anumit timp icircl retransmite
Icircn momentul icircn care se primeşte un segment TCP trimite o confirmare (din motive de
eficienţă aceasta poate fi amacircnată un anumit interval de timp)
Icircn headerul TCP este menţinută o sumă de control pentru detectarea modificărilor icircn date
Dacă se recepţionează un segment corupt TCP icircl ignoră urmacircnd să fie retransmis datorită
neprimirii confirmării
Deoarece segmentele TCP sunt transmise mai departe icircncapsulate icircn datagrame IP iar
acestea pot ajunge icircn orice ordine segmentele TCP pot ajunge icircn altă ordine decacirct cea icircn
care au fost trimise De aceea la destinaţie TCP-ul trebuie să se folosească de numere de
secvenţă pentru a reordona eventual segmentele icircnainte de a le livra către nivelul
aplicaţie De asemenea TCP trebuie să asigure ignorarea duplicatelor
TCP asigură controlul fluxului icircn condiţiile icircn care viteza de trimitere a datelor de la sursă
poate fi mult prea mare decacirct capacitatea de prelucrare de la destinaţie
Serviciul oferit de TCP este de tip flux de octeţi deoarece oferă garanţii că fluxul de date trimis
de sursă va fi livrat fără modificări la destinaţie Comparativ UDP-ul produce pentru fiecare
transfer cerut de nivelul aplicaţie un pachet IP (care ulterior poate fi supus fragmentării) care
dacă ajunge la destinaţie corect va fi livrat direct nivelului aplicaţie fără a garanta icircn vreun fel
ordinea
2 Formatul pachetelor TCP
Pachetele de date transmise de TCP segmentele sunt formate dintr-un antet (figura 72) de 20
octeţi urmat de datele primite de la nivelul aplicaţie Antetul poate uneori conţine şi o serie de
opţiuni caz icircn care poate ajunge la 60 octeţi
Figura 72 Structura unui segment TCP
Antetul unui segment TCP cuprinde
port sursă - 16 biţi pentru specificarea portului aplicaţiei transmiţătoare
port destinaţie - 16 biţi pentru specificarea portului aplicaţiei ce recepţionează segmentul
TCP
Aceste două porturi icircmpreună cu adresele ale sursei şi destinaţiei conţinute icircn antet-ul IP
identifică icircn mod unic conexiunea Pentru o pereche formată dintr-o adresă IP şi un port
se foloseşte adesea denumirea de socket (denumire introdusă icircn specificaţiile iniţiale ale
protocolului TCP icircn RFC 793)
număr de secvenţă - 32 biţi
Pentru a asigura un serviciu de tip flux de octeţi TCP numerotează fiecare octet de date
utilizacircnd un număr de secvenţă Numărul de secvenţă din cadrul antetului TCP specifică
destinaţiei care este primul octet din fluxul trimis La iniţierea unei conexiuni se setează
flag-ul SYN şi se alege aleator un număr de secvenţă de icircnceput utilizacircnd un generator de
numere de secvenţă ISN (Initial sequence number) Numărul de secvenţă al primului
octet de date va fi numărul generat ISN plus 1 deoarece pachetul de iniţiere (cu SYN
setat) consumă şi el un număr de secvenţă Se va vedea mai departe că şi flag-ul de
terminare a conexiunii FIN consumă şi el un număr de secvenţă
confirmare - 32 biţi
Reprezintă numărul de secvenţă al octetului de date pe care transmiţătorul confirmării se
aşteaptă să-l primească Astfel dacă s-a recepţionat octetul cu numărul de secvenţă x (icircn
numerotaţia sursei) pachetul de confirmare va avea flag-ul ACK setat şi va conţine
numărul de confirmare x + 1 Trimiterea unui ACK nu consumă un număr de secvenţă
deoarece atacirct acest cacircmp cacirct şi flag-ul ACK fac parte din antet şi după stabilirea
conexiunii ambele cacircmpuri devin active Acest mecanism nu permite confirmări selective
pentru că numărul de secvenţă specifică pacircnă unde s-au recepţionat date De exemplu
dacă la destinaţie au ajuns octeţii 1-1024 şi următorul segment primit conţine octeţii
2049-3072 nu se poate trimite confirmare pentru cel de-al doilea segment deci
confirmarea va cuprinde numărul de secvenţă 1025
lungimea antetului - 4 biţi
Specifică dimensiunea antetului ca număr de cuvinte de 32 de biţi (4 octeţi) Antetul
poate avea icircntre 20 şi 60 de octeţi deci valoarea acestui cacircmp va fi icircntre 5 (5 x 4 = 20
octeţi) şi 15 (15 x 4 = 60)
6 biţi rezervaţi pentru utilizări viitoare
6 biţi de control reprezentacircnd următoarele flag-uri ce pot fi setate simultan
o URG - cacircmpul urgent pointer este valid
o ACK - cacircmpul de confirmare este valid
o PSH - destinaţia trebuie să trimită datele către nivelul aplicaţie cacirct mai devreme
o RST - se doreşte resetarea conexiunii
o SYN - iniţierea conexiunii
o FIN - icircnchiderea conexiunii
dimensiunea ferestrei - 16 biţi
Reprezintă numărul de octeţi (icircncepacircnd cu numărul de secvenţă conţinut icircn cacircmpul de
confirmare) pe care destinaţia e dispusă să-l primească Este limitat la 65535 octeţi dar
cu toate că pare o limită destul de mare există situaţii cacircnd se doresc valori mult mai
mari Icircn acest scop se folosesc nişte opţiuni speciale descrise ceva mai tacircrziu care permit
scalarea ferestrei
suma de control - 16 biţi
Această sumă de control acoperă icircntregul segment TCP (atacirct datele cacirct şi antetul TCP) şi
spre deosebire de UDP este obligatoriu să fie completat de transmiţător şi verificat de
receptor Dar ca şi icircn cazul UDP-ului la calculul sumei de control se ia in considerare şi
o zona specială de 12 octeţi ce cuprinde pentru re-verificare cacircmpuri din antetul IP
(adresa IP a sursei şi a destinaţiei)[aici tre sa vina o referire la poza cu pseudo-antetu]
După adăugarea acestui pseudo-antet datele se icircmpart icircn cuvinte de 16 biţi icircn vederea
calculării sumei de control adăugacircndu-se eventual şi un octet de aliniere
urgent pointer - 16 biţi
Este utilizat pentru specificarea deplasamentului ultimului octet de date trimis icircn regim
urgent Astfel ultimul octet din secvenţa urgentă se obţine adunacircnd acest cacircmp la
numărul de secvenţă Ce icircnseamnă acest mod urgent de transmitere există situaţii icircn care
aplicaţiile vor să trimită date `neordonate` Să presupunem că aplicaţia a trimis către
nivelul transport o cantitate mare de date dar la un moment dat observă ceva icircn neregulă
şi doreşte să anuleze operaţia Dacă trimite o comandă de anulare aceasta va fi adăugată
la sfacircrşitul şirului de octeţi deci nu se va putea icircmpiedica ajungerea acestora la nivelul
aplicaţie de la receptor Activacircnd modul urgent datele urgente (comanda de anulare) vor
fi plasate la icircnceputul pachetului Aplicaţiile mai cunoscute care folosesc acest mod sunt
Telnet Rlogin şi FTP
opţiuni - pacircnă la 40 de octeţi (figura 73)
Cele mai utilizate opţiuni sunt
o Sfacircrşit de opţiuni (end of option) - 1 octet
Este utilizat pentru alinierea datelor conţinute icircn cacircmpul de opţiuni Nu poate fi
utilizat decacirct o singură dată marcacircndu-se astfel sfacircrşitul opţiunilor şi icircnceperea
datelor efective Dacă pentru alinierea la un cuvacircnt de 32 de biţi e nevoie de mai
mult de 1 byte se va utiliza opţiunea no operation Orice apare după această
opţiune pacircnă la icircnceputul cuvacircntului următor de 32 de biţi e ignorat
o no operation - 1 octet
Utilizat pentru alinierea la cuvinte de 32 de biţi
o Dimensiunea maximă a segmentului (Maximum Segment Size (MSS)) - 16 biţi
Icircn ciuda denumirii defineşte lungimea maximă a datelor nu dimensiunea
icircntregului segment Poate lua valori icircntre 0 şi 65535 valoarea implicită fiind 536
Această opţiune e valabilă doar icircn pachetele de iniţiere a conexiunii (cele cu flag-
ul SYN setat) fiecare parte făcacircnd cunoscută dimensiunea maximă a datelor
dispusă să le primească icircntr-un pachet Icircn principiu cu cacirct această valoarea e mai
mare e mai bine (deoarece se recuperează din spaţiul ocupat de antetele TCP şi
IP) pacircnă cacircnd apare fragmentarea Valoarea maximă la care se poate seta este
MTU (Maximum Transfer Unit) minus dimensiunea antetului IP şi TCP (1460
octeţi icircn cazul Ethernet)
o Factor de scalare a ferestrei (Window scale factor) - 1 octet
Pentru situaţiile icircn care se doreşte utilizarea unei ferestre mai mare de 65535 bytes
se poate utiliza acest cacircmp pentru mărirea dimensiunii ferestrei Noua dimensiune
va fi Chiar dacă
factorul de scalare poate fi maxim 255 icircn cazul TCPIP el nu poate depăşi
valoarea 16 deoarece dimensiunea maximă a ferestrei nu poate fi mai mare decacirct
valoarea celui mai mare număr de secvenţă ( )
Acest factor se poate seta doar la iniţierea conexiunii Icircn timpul transferului de
date se poate modifica dimensiunea ferestrei dar factorul de scalare rămacircne
acelaşi Dacă cel care a iniţiat conexiunea a trimis icircn segmentul de iniţiere şi acest
factor dar icircn pachetul cu ACK destinatarul nu şi-a trimis şi el factorul atunci se la
considera 0 icircn ambele direcţii Invers dacă cel care solicită deschiderea
conexiunii nu setează factorul destinaţia nu va putea seta factorul de scalare
o Timestamp - 10 octeţi
Utilizat pentru reţinerea timpului icircn vederea calculării RTT (Round Trip Time)
Cacircmpul timestamp e completat de sursă icircn momentul trimiterii segmentului La
destinaţie valoarea este reţinută şi copiată icircn cacircmpul timestamp echo reply al
pachetului cu confirmarea RTT-ul este calculat de sursă făcacircnd diferenţa dintre
timpul curent şi această valoare
Figura Opţiuni TCP
3 Iniţierea şi terminarea unei conexiuni TCP
TCP este un protocol orientat conexiune deci presupune stabilirea unei căi virtuale icircntre sursă şi
destinaţie
Subsections
Protocolul de iniţiere
o 1 Deschiderea simultană
Protocolul de terminare
o 2 Terminarea simultană
o 3 Resetarea conexiunii
Diagrama de stări
Protocolul de iniţiere
Modul de transmisie icircn cazul protocolului TCP este full-duplex deci sunt transmise date
simultan icircn ambele direcţii Aceasta presupune că cel care iniţiază conexiunea trebuie să
primească aprobarea celuilalt capăt icircnainte de icircnceperea transferului de date sursa icircşi anunţă
intenţia de a iniţia o conexiune destinaţia trimite un pachet cu confirmarea cererii şi un pachet de
iniţiere a conexiunii de la el la sursă iar apoi sursa confirmă cererea primită de la destinaţie Paşii
2 şi 3 pot fi realizaţi prin trimiterea unui singur pachet de aceea protocolul de iniţiere este
cunoscut sub numele de three-way handshake
Icircn cadrul protocolului de iniţiere există 2 tipuri de cereri de iniţiere cerere activă (active open)
iniţiată de clientul ce doreşte să stabilească conexiunea cu serverul şi cerere pasivă (passive
open) din partea serverului
Cei 3 paşi sunt
1 Clientul trimite un segment cu flag-ul SYN setat şi care conţine portul sursă portul de la
destinaţie şi numărul de secvenţă generat iniţial (ISN) de la care se vor numerota octeţii
de la client către server Opţional se pot stabili parametrii conexiunii prin setarea lungimii
maxime a segmentelor (MSS) dispus să le primească de la server factorului de scalare a
ferestrei Acest prim segment nu conţine nici un parametru de confirmare şi de asemenea
nu are rost să conţine să seteze dimensiunea ferestrei
2 Al doilea segment e trimis de server şi are un rol dublu confirmă segmentul primit de la
client prin setarea flag-ului ACK şi completează numărul de secvenţă cu numărul de
secvenţă primit plus 1 şi al doilea rol iniţializează conexiunea de la el către client prin
setarea flag-ului SYN şi generarea unui număr de secvenţă iniţial ce va fi folosit icircn
numerotarea octeţilor de la server spre client Pe lacircngă aceasta trebuie să conţină
dimensiunea ferestrei şi opţional poate seta factorul de scalare şi dimensiunea maximă a
segmentului acceptat
3 Clientul trimite un segment cu confirmarea cererii din partea serverului (ACK setat +
completează numărul confirmat cu numărul de secvenţa primit + 1) Ca şi icircn cazul
pasului 2 trebuie să seteze dimensiunea ferestrei Acest pachet poate conţine date
Subsections
1 Deschiderea simultană
1 Deschiderea simultană
Se poate icircntacircmpla ca uneori cele două capete care vor să comunice să icircncerce să stabilească
conexiunea simultan Icircn acest caz după ce fiecare a trimis segmentul de iniţiere (iniţiere activă)
ambele vor trimite un segment cu SYN + ACK şi se va stabili o singură conexiune nu două
Protocolul de terminare
Oricare dintre cele două părţi poate solicita icircnchiderea conexiunii dar conexiunea fiind full-
duplex transferul de date icircn celălalt sens poate continua (această situaţie e denumită half-close)
O icircnchidere completă a unei conexiuni TCP presupune următorii paşi
1 Clientul trimite un segment cu flag-ul FIN activat solicitacircnd icircnchiderea conexiunii
2 Serverul trimite un segment ACK confirmacircnd primirea cererea Numărul de confirmare
se completează normal ca numărul de secvenţă primit + 1
3 Serverul continuă să trimită date către client şi cacircnd doreşte să icircnchidă şi el conexiunea
trimite un segment cu FIN activat
4 Clientul trimite un pachet ACK confirmacircnd icircnchiderea conexiunii
Cel care iniţiază primul procedura de icircnchidere (trimite primul FIN) realizează o icircnchidere activă
(active close) iar celălalt capăt o icircnchidere pasivă (passive close) Icircn mod normal cel care
realizează iniţierea activă va fi primul ce va trimite FIN dar oricare dintre cei doi poate icircnchide
activ conexiunea
Subsections
2 Terminarea simultană
3 Resetarea conexiunii
2 Terminarea simultană
Icircn mod similar cu deschiderea simultană există posibilitatea ca ambele capete ale conexiunii TCP
să iniţieze simultan procedura de icircnchidere a conexiunii Icircn acest caz ambele părţi vor trimite
FIN şi vor aştepta primirea unui ACK Icircn continuare fiecare va primi cererea de terminare şi va
trimite ACK Se observă că numărul de segmente transferate pentru realizarea icircnchiderii
conexiunii (4 segmente) este acelaşi ca la terminarea normală
3 Resetarea conexiunii
Există situaţii icircn care TCP doreşte resetarea conexiunii De exemplu dacă se solicită iniţierea
unei conexiuni la un port inexistent Icircn acest caz cealaltă parte va trimite un segment cu bitul
RST setat pentru a anula solicitarea O altă situaţie este atunci cacircnd se constată că celalalt capăt
al conexiunii nu răspunde un anumit timp (timeout)
Diagrama de stări
Toate evenimentele ce au loc icircn timpul stabilirii conexiunii transferului şi icircnchiderii conexiunii
pot fi rezumate printr-un automat finit cunoscut sub numele de diagrama de stări După cum
chiar numele sugerează este o maşină cu un număr limitat de stări O stare este păstrată pacircnă icircn
momentul apariţiei unui eveniment moment icircn care se poate trece icircn altă stare şisau efectua o
acţiune
Aceste stări posibile sunt (denumirile sunt asemănătoare cu cele utilizate de netstat) cele din
tabelul 71
Tabela Stările diagramei de stări TCP
Stare Descriere
CLOSED Nu există conexiune
LISTEN Serverul aşteaptă cereri de la clienţi
SYN_SENT Cerere de iniţiere (activă) a conexiunii Se
aşteaptă confirmarea
SYN_RCVD S-a primit o cerere de iniţiere conexiune
ESTABLISHED S-a stabilit conexiunea
FIN_WAIT_1 Aplicaţia a solicitat icircnchiderea conexiunii
FIN_WAIT_2 Serverul a acceptat icircnchiderea conexiunii
CLOSING Ambele părţi solicită simultan icircnchiderea
conexiunii
TIME_WAIT Conexiune icircnchisă dar se aşteaptă ca
pachetele retransmise să dispară
CLOSE_WAIT Serverul aşteaptă icircnchiderea dinspre partea
aplicaţiei
LAST_ACK Serverul a icircnchis conexiunea Aşteaptă
ultima confirmare
Icircn diagrama ilustrată icircn figura 74 putem observa 3 tipuri de tranziţii icircntre cele 11 stări tranziţii
ce corespund unei funcţionări normale pentru client (linii normale continue) pentru server (linii
normale icircntrerupte) şi tranziţii pentru situaţii nestandard (linii subţiri continue)
O comportarea normală pentru client presupune parcurgerea următoarelor stări CLOSED
SYN_SEND ESTABLISHED FIN_WAY_1 FIN_WAY_2 TIME_WAIT
Iniţial clientul TCP se află icircn starea CLOSED
Aşteptacircnd icircn starea CLOSED clientul poate primi de la aplicaţie o cerere de iniţiere
activă a unei conexiuni Trimite un segment SYN şi trece icircn starea SYN_SENT
Icircn starea SYN_SENT clientul aşteaptă de la server un segment ACK+SYN după care
trimite un ACK şi trece icircn starea ESTABLISHED Din acest moment poate icircncepe
transferul efectiv de date Clientul va rămacircne icircn această stare cacirct timp are de trimisprimit
date
Aflat icircn această stare clientul TCP poate primi din partea aplicaţiei o cerere de icircnchidere a
conexiunii Icircn acest caz va trimit un segment FIN şi trece icircn starea FIN_WAIT_1
Icircn această stare clientul aşteaptă ACK din partea serverului După ce-l primeşte
conexiunea icircntr-un sens se va icircnchide şi clientul trece icircn starea FIN_WAIT_2
Starea FIN_WAIT_2 durează pacircnă cacircnd primeşte cererea de icircnchidere a conexiunii FIN
din partea serverului Trimite ACK şi va trece icircn starea TIME_WAIT
Icircn această stare se va porni un timer cu valoarea setată la dublul timpului de viaţă estimat
pentru un segment de lungime maximă MSL (Maximum Segment Lifetime) Acest timer
permite retransmiterea ACK-ului icircn cazul icircn care acesta se pierde (celălalt capăt va da
timeout şi va retransmite segmentul FIN) Icircn tot acest time cei doi sockeţi (de la client şi
server) nu vor putea fi reutilizaţi Totodată pachetele icircntacircrziate care sosesc icircn această
perioadă sunt ignorate După expirarea acestui timer clientul revine icircn starea iniţială
CLOSED
Din punctul de vedere al unui server o comportare standard parcurge următoarele stări
CLOSED LISTEN SYN_RCVD ESTABLISHED CLOSE_WAIT şi LAST_ACK
Iniţial serverul TCP se află icircn starea CLOSED
Icircn această stare poate primi de la aplicaţia server o cerere de iniţiere activă şi trece icircn
starea LISTEN
Aflat icircn starea LISTEN serverului TCP poate recepţiona un segment SYN de la un client
TCP Icircn acest caz va trimite ACK+SYN şi va trece icircn starea SYN_RCVD
Icircn această stare serverul aşteaptă primirea confirmării de la client moment icircn care
conexiunea e stabilită icircn ambele sensuri şi se poate icircncepe transferul de date (starea
ESTABLISHED)
Clientul TCP poate solicita icircnchiderea conexiunii trimiţacircnd un segment FIN către server
Icircn acest caz serverul TCP trimite confirmarea şi trece icircn starea CLOSE_WAIT
Icircn această stare serverul aşteaptă să primească din partea programului server icircnchiderea
conexiunii moment icircn care va trimite către client un segment FIN şi trece icircn starea
LAST_ACK
Serverul aşteaptă primirea ultimei confirmări de la client după care revine icircn starea
CLOSED
Atacirct serverul cacirct şi clientul TCP se pot afla icircn oricare din cele 11 stări ale diagramei
Figura Diagrama de stări pentru TCP
4 Controlul fluxului
Dacă icircncă de la icircnceput s-a reuşit stabilirea formatului unui pachet TCP şi a modulului icircn care
trebuie să se facă icircnchiderea şi deschiderea unei conexiuni nu acelaşi lucru se poate spune şi
despre modul icircn care ar trebui să se realizeze controlul fluxului Ţinacircnd seama icircnsă că din 1989
(de cacircnd datează RFC-ul 2581 cel despre care am menţionat că specifică icircn mod clar modul icircn
care trebuie să se comporte o implementare de TCP) TCP-ul a rămas neschimbat putem să icircl
considerăm un rezultat important al domeniului reţelor de calculatoare
Icircn cele ce urmează vom icircnţelege prin controlul fluxului totalitatea algoritmilor care permit
atingerea unei viteze de transfer punct-la-punct cacirct mai mare pentru toate conexiunile existente
Icircn principal aceşti algoritmi stabilesc modul icircn care segmentele şi confirmările trebuie trimise şi
ce acţiuni trebuie executate icircn situaţiile icircn care răspunsurile aşteptate de la celălalt capăt icircntacircrzie
să vină
Subsections
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
Icircntacircrzierea confirmărilor
O modalitate simplă de generare a confirmărilor este de a trimite cacircte una pentru fiecare segment
primit Această politică prezintă avantajul de a face comunicaţia self-clocking icircnsă este
ineficientă dacă segmentele care nu conţin decacirct confirmări sunt urmate la scurtă distanţă (cacircteva
zeci de milisecunde) de segmente ce conţin date efective Pentru a evita această situaţie se
procedează2 la icircntacircrzierea (200ms este o valoare uzuală icircn RFC 1122 se specifică o valoare
maximă de 500ms) a segmentelor care conţin doar confirmări Această strategie face posibil ca
un răspuns generat de primirea unor date să plece sper celălalt capăt icircn acelaşi segment cu
confirmarea
Observaţie deoarece este dificil de menţinut timere pentru fiecare confirmare diferenţa de
200ms este calculată de un timer global Din acest motiv modul efectiv de comportare poate fi
descris şi icircn felul următor cacircnd un segment nu conţine decacirct o confirmare el este pus icircntr-o
coadă ce va fi inspectată de un proces care din 200 icircn 200 ms trimite tot ce s-a acumulat icircn
coada
Footnotes
2
Acest comportament a fost propus de David D Clark icircn iulie 1982 icircn RFC 813
Algoritmul Nagle
Acest algoritm3 icircncearcă să icircmbunătăţească performanţele exploatacircnd următoarea caracteristică
foarte des icircntacirclnită icircn dialogul dintre două staţii dacă se icircncearcă trimiterea unor date de
dimensiune mică icircnsă există icircncă date neconfirmate de partener atunci ele sunt buffer-ate şi
trimise icircntr-un segment mai mare cacircnd soseşte confirmarea aşteptată Icircn acest fel se poate evita
generarea datagramelor mici (tinygrame) icircn situaţia unei legături lente Icircn cazul unei legături
rapide confirmările vor veni repede şi icircntacircrzierea introdusă de algoritm va neglijabilă
Există icircnsă şi cazuri icircn care acest algoritm duce la deprecierea performanţelor mesajele scurte
generate de mişcările mouse-ului icircn cazul folosirii unui server X Window sau utilizarea tastelor
care trimit mai mult de un caracter (secvenţe escape) Pentru a rezolva aceste inconveninte API-
ul de utilizare a TCP-ului trebuie să ofere o modalitate de a dezactiva acest algoritm (icircn sistemele
bazate pe sockeţi există icircn acest scop opţiunea TCP_NODELAY)
Footnotes
algoritm3
Algoritmul aparţinacircnd lui John Nagle a fost propus icircn ianuarie 1984 icircn RFC 896
Fereastra glisantă
Algoritmul implementat de TCP pentru a implementa transferul sigur de date este cunoscut icircn
teorie sub numele de Go-Back-N Icircn acest algoritm se utilizează numere de secvenţă pentru a
distinge pachetele icircntre ele şi o coadă (dimensiunea maximă a cozii reprezintă fereastra) de
pachetele a căror confirmare se aşteaptă Pachetele se icircmpart icircn 4 categorii
1 pachete trimis şi pentru care s-a primit confirmare
2 pachete trimise şi pentru care se aşteaptă icircncă confirmarea
3 pachete care nu au fost trimise icircncă dar care nu depăşesc limitele ferestrei şi deci pot fi
trimise
4 pachete care icircncă nu au fost trimite şi care nici nu vor putea fi trimise decacirct după ce au
fost trimise toate pachetele din categoria 3 şi s-au primit o parte din confirmările la
pachetele din categoria 2
Dacă confirmările pentru pachetele din categoria 2 icircntacircrzie prea mult (un mecanism de timer-e
informează asupra acestui lucru) atunci ele vor fi retrimise Icircn versiunea iniţială TCP-ul nu
permitea decacirct confirmări pozitive ceea ce icircnseamnă că avansarea ferestrei se va icircmpotmoli la
segmentele neconfirmate Cum se poate evita aceasta situaţie vom discuta icircn detaliu icircn capitolele
următoare O soluţie foarte radicală o constituie introducerea de confirmări selective (acest lucru
este realizat de RFC 2018 din octombrie 1996) Această modifică face ca TCP-ul actual să fie un
hibrid de Go-Back-N şi Selective Repeat
Deoarece dimensiunea ferestrei este anunţată la fiecare segment un client lent poate ca pe măsură
ce trimite confirmările să informeze despre progresul icircnregistrat la livrarea datelor următorului
nivel (aplicaţie) Dacă datele vin prea repede pentru viteza cu care clientul procesează datele
fereastra fereastra se va dimiua şi chiar icircnchide (acest lucru se realizează anunţacircnd o fereastră de
dimensiune zero) Cum se realizează efectiv redeschiderea vom analiza icircntr-un capitol viitor
Slow start
Un transfer de date TCP poate să icircnceapă prin transmiterea de segmente pacircnă la umplerea
icircntregii ferestre după care fie se primesc confirmări care vor permite unor noi pachete să fie
trimise fie vor expira timer-ele de retransmisie şi se va icircncepe retrimiterea pachetelor de la
icircnceputul ferestrei Din păcate un astfel de comportament poate duce la pomparea icircn reţea a unui
număr de pachete prea mare pentru capacitatea disponibilă efectiv icircnrăutăţind congestia Pentru
a evita acest lucru s-a propus următoarea soluţie4 iniţial se trimite un segment după primirea
confirmării lui se trimit două segmente după sosirea confirmărilor pentru ele se trimit patru
segmente şi aşa mai departe La un moment dat fie vor icircncepe să se piardă segmente (un indiciu
că s-a atins capacitatea maximă a canalului) fie se va umple fereastra pe care o anunţă cel care
primeşte Trebuie să remarcam că datorită creşterii exponenţiale a numărului de segmente se va
atinge destul de repede una din cele două situaţii
Modalitatea efectivă de implementare a acestui algoritm are la bază utilizarea unei ferestre de
congestie (congestion window cwnd) care este iniţializată cu dimensiunea unui segment (cwnd
se calculează icircn octeţi) şi la fiecare pas este dublată fereastra efectivă din cadrul căreia se pot
trimite segmente este dată de minimul dintre ultima fereastra comunicată de partener şi cwnd
Footnotes
soluţie4
Soluţia aparţine lui V Jacobson şi a fost prezentată icircn 1988 la conferinţă ACM
SIGCOMM-88
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Deoarece TCP trebuie să funcţioneze icircn condiţii variate de latenţă modul icircn care se face
retransmiterea trebuie să fie cacirct mai flexibil (şi simplu icircn acelaşi timp pentru a introduce un
overhead cacirct mai mic) Timpul cacirct se aşteaptă venirea unei confirmări (retransmission timeout
RTO) este calculat prin cronometrarea timpului care icirci ia unui segment trimis să fie confirmat
Pentru o anumită conexiune se cronometrează cacircte un singur segment la un moment dat iar pe
baza RTT-ului măsurat se actualizează valoare RTO-ului
Icircn RFC 793 formula de calcul a RTO-ului este următoarea
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
4 Controlul fluxului
o 3 Studii de caz
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
Bibliografie
About this document
7 Protocoale TCPIP la nivelul transport
Subsections
1 UDP
o 1 Caracteristici UDP
o 2 Formatul pachetelor UDP
2 TCP
o 1 Caracteristici TCP
o 2 Formatul pachetelor TCP
o 3 Iniţierea şi terminarea unei conexiuni TCP
Protocolul de iniţiere
1 Deschiderea simultană
Protocolul de terminare
2 Terminarea simultană
3 Resetarea conexiunii
Diagrama de stări
o 4 Controlul fluxului
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
3 Studii de caz
o 1 Fragmentarea pachetelor UDP
o 2 Stabilirea şi eliberarea unei conexiuni TCP
o 3 Transferul de date TCP
1 UDP
Subsections
1 Caracteristici UDP
2 Formatul pachetelor UDP
1 Caracteristici UDP
UDP (User Datagram Protocol) este un protocol de nivel transport construit special pentru a oferi
un serviciu de comunicare cacirct mai simplu peste IP Specificaţiile protocolului au fost publicate icircn
1980 icircn RFC-ul cu numărul 7681
Cacircteva caracteristici ale UDP-ului sunt
este un serviciu de tip datagramă cererile de trimitere de date primite de la nivelul
superior sunt tratate independent
comunicarea are loc fără stabilirea unei legături (conection-less) nu există mecanisme de
stabilire şi terminare a unei conexiuni deoarece toate datele sunt trimise icircn cadrul unui
singur pachet IP care eventual va fi supus fragmentării
nu se garantează ajungerea ala destinaţie a datelor (best effort) ajungerea la destinaţie nu
este anunţată sursei
datele transportate sunt protejate de o sumă de control (introdusă ca opţională iniţial ea
este trecută ca necesară(must) icircn RFC 1122 care stabileşte modul de comportare al
clienţilor icircn Internet)
overhead-ul introdus este minim doar 8 octeţi
Cacircteva utilizări tipice ale UDP-ului
servicii de rezolvare a numelor (DNS) deoarece icircntrebările şi răspunsurile 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 fişiere (NFS) deoarece acest tip de aplicaţii sunt icircn general rulate icircn reţele
locale cu performanţe ridicate care nu necesită mecanismele TCP
managementul reţelei (SNMP)
protocoale de rutare (RIP)
Footnotes
7681
RFC 768 are nici mai mult nici mai puţin decacirct 3 pagini nu conţine cuprins dar are o listă
de 5 referinţe bibliografice
2 Formatul pachetelor UDP
Datagramele UDP sunt formate dintr-un antet (figura 71) urmat de datele care se doresc
transmise (dacă există)
Figura 71 Structura unei datagrame UDP
Antetul cuprinde
port sursă - 16 biţi
Icircmpreună cu adresa IP a sursei acest număr identifică icircn mod unic locul de unde a fost
trimis datagrama UDP
port destinaţie - 16 biţi
Icircmpreună cu adresa IP a destinaţiei acest număr identifică icircn mod unic destinaţia dorită
pentru datagrama UDP
lungimea pachetului UDP - 16 biţi
Lungimea minimă măsoară datagrama UDP cu tot cu antent şi prin urmare are o valoare
minimă de 8 octeţi
sumă de control - 16 biţi
Suma de control acoperă icircntreg pachetul UDP cacirct şi un pseudo antet de 12 octeţi format
din
adresa IP a sursei - 32 biţi
o adresa IP a destinaţiei - 32 biţi
8 biţi de zero pentru aliniere
numărul protocolului UDP (17) reprezentat pe 8 biţi
lungimea pachetului UDP - 16 biţi
Deoarece suma de control necesită icircn calculul ei un număr multiplu de 16 octeţi la
sfacircrşitul datelor se adaugă un număr potrivit de octeţi de zero Dacă suma este 0 atunci ea
va fi stocată ca 65535 (toţi biţii pe 1) Un 0 icircn cacircmpul de sumei de control indică faptul
că suma de control nu a fost calculată Observaţie chiar dacă un client are inhibat (icircn
mod explicit) calcului sumei de control el este obligat să verifice suma pachetelor care
sosesc şi au suma calculată
2 TCP
Subsections
1 Caracteristici TCP
2 Formatul pachetelor TCP
3 Iniţierea şi terminarea unei conexiuni TCP
o Protocolul de iniţiere
1 Deschiderea simultană
o Protocolul de terminare
2 Terminarea simultană
3 Resetarea conexiunii
o Diagrama de stări
4 Controlul fluxului
o Icircntacircrzierea confirmărilor
o Algoritmul Nagle
o Fereastra glisantă
o Slow start
o Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
o Evitarea congestiei
o Fast Retransmission Fast Recovery
o Sindromul ``Silly Window
o TCP Keepalive Timer
1 Caracteristici TCP
Deoarece protocolul IP este de tip datagramă utilizarea lui direct icircn aplicaţii care in general au
nevoie de conexiuni sigure este mult prea anevoioasă Din aceste motive peste IP a fost construit
un alt protocol TCP (transimission control protocol) care corectează aceste probleme Prima
definire se găseşte icircn RFC-ul cu numărul 793 şi datează din septembrie 1981 Din cauza deselor
congestii apărute icircn 1986 algoritmul care stă la baza TCP-ului este reanalizat şi icircn octombrie
1989 icircn RFC-ul cu numărul 1122 este publicată o nouă specificare mult mai eficientă şi
neambiguă a TCP-ului Noi probleme legate de viteze mari sunt tratate icircn RFC-ul 1323 iar icircn
2018 TCP-ul este extins pentru a permite confirmările selective (selective acknowledge) Seria
de RFC-urie fundamentale este icircncheiată de apariţia icircn 1989 a RFC-ului cu numărul 2581 Icircn el
se specifică foarte strict comportamentul care este permis pentru o implementare de TCP
Alături de protocolul UDP TCP se situează pe nivelul transport icircn ierarhia de protocoale deci
icircntre nivelul aplicaţie şi nivelul reţea Dar cu toate că se bazează pe acelaşi protocol (IP) ca şi
UDP TCP furnizează către nivelul aplicaţie cu totul alt tip de servicii servicii orientate-
conexiune sigure de tip flux de octeţi
Termenul de orientat-conexiune presupune că icircntre cele două aplicaţii care comunică utilizacircnd
TCP trebuie să se stabilească o conexiune TCP icircnainte ca transferul de date să aibă loc Această
conexiune nu este efectiv una fizică ci virtuală asemănător cum se icircntacircmplă icircn sistemul de
telefonie clasică cineva formează un număr şi abia icircn momentul icircn care cealaltă persoană
răspunde se poate icircncepe conversaţia Fiind o conexiune host-la-host nu există noţiunile de
broadcast sau multicast
Transferul sigur de date este asigurat icircn următorul mod
Datele sunt icircmpărţite icircn bucăţi a căror dimensiune optimă e determinată de TCP spre
deosebire de UDP care trimite datagrame UDP corespunzătoare cu dimensiunea datelor
primite de la nivelul aplicaţie Unitatea de date trimisă de TCP către nivelul reţea poartă
numele de segment
Cacircnd TCP trimite un segment porneşte un timer şi dacă nu se primeşte confirmarea
segmentului respectiv icircntr-un anumit timp icircl retransmite
Icircn momentul icircn care se primeşte un segment TCP trimite o confirmare (din motive de
eficienţă aceasta poate fi amacircnată un anumit interval de timp)
Icircn headerul TCP este menţinută o sumă de control pentru detectarea modificărilor icircn date
Dacă se recepţionează un segment corupt TCP icircl ignoră urmacircnd să fie retransmis datorită
neprimirii confirmării
Deoarece segmentele TCP sunt transmise mai departe icircncapsulate icircn datagrame IP iar
acestea pot ajunge icircn orice ordine segmentele TCP pot ajunge icircn altă ordine decacirct cea icircn
care au fost trimise De aceea la destinaţie TCP-ul trebuie să se folosească de numere de
secvenţă pentru a reordona eventual segmentele icircnainte de a le livra către nivelul
aplicaţie De asemenea TCP trebuie să asigure ignorarea duplicatelor
TCP asigură controlul fluxului icircn condiţiile icircn care viteza de trimitere a datelor de la sursă
poate fi mult prea mare decacirct capacitatea de prelucrare de la destinaţie
Serviciul oferit de TCP este de tip flux de octeţi deoarece oferă garanţii că fluxul de date trimis
de sursă va fi livrat fără modificări la destinaţie Comparativ UDP-ul produce pentru fiecare
transfer cerut de nivelul aplicaţie un pachet IP (care ulterior poate fi supus fragmentării) care
dacă ajunge la destinaţie corect va fi livrat direct nivelului aplicaţie fără a garanta icircn vreun fel
ordinea
2 Formatul pachetelor TCP
Pachetele de date transmise de TCP segmentele sunt formate dintr-un antet (figura 72) de 20
octeţi urmat de datele primite de la nivelul aplicaţie Antetul poate uneori conţine şi o serie de
opţiuni caz icircn care poate ajunge la 60 octeţi
Figura 72 Structura unui segment TCP
Antetul unui segment TCP cuprinde
port sursă - 16 biţi pentru specificarea portului aplicaţiei transmiţătoare
port destinaţie - 16 biţi pentru specificarea portului aplicaţiei ce recepţionează segmentul
TCP
Aceste două porturi icircmpreună cu adresele ale sursei şi destinaţiei conţinute icircn antet-ul IP
identifică icircn mod unic conexiunea Pentru o pereche formată dintr-o adresă IP şi un port
se foloseşte adesea denumirea de socket (denumire introdusă icircn specificaţiile iniţiale ale
protocolului TCP icircn RFC 793)
număr de secvenţă - 32 biţi
Pentru a asigura un serviciu de tip flux de octeţi TCP numerotează fiecare octet de date
utilizacircnd un număr de secvenţă Numărul de secvenţă din cadrul antetului TCP specifică
destinaţiei care este primul octet din fluxul trimis La iniţierea unei conexiuni se setează
flag-ul SYN şi se alege aleator un număr de secvenţă de icircnceput utilizacircnd un generator de
numere de secvenţă ISN (Initial sequence number) Numărul de secvenţă al primului
octet de date va fi numărul generat ISN plus 1 deoarece pachetul de iniţiere (cu SYN
setat) consumă şi el un număr de secvenţă Se va vedea mai departe că şi flag-ul de
terminare a conexiunii FIN consumă şi el un număr de secvenţă
confirmare - 32 biţi
Reprezintă numărul de secvenţă al octetului de date pe care transmiţătorul confirmării se
aşteaptă să-l primească Astfel dacă s-a recepţionat octetul cu numărul de secvenţă x (icircn
numerotaţia sursei) pachetul de confirmare va avea flag-ul ACK setat şi va conţine
numărul de confirmare x + 1 Trimiterea unui ACK nu consumă un număr de secvenţă
deoarece atacirct acest cacircmp cacirct şi flag-ul ACK fac parte din antet şi după stabilirea
conexiunii ambele cacircmpuri devin active Acest mecanism nu permite confirmări selective
pentru că numărul de secvenţă specifică pacircnă unde s-au recepţionat date De exemplu
dacă la destinaţie au ajuns octeţii 1-1024 şi următorul segment primit conţine octeţii
2049-3072 nu se poate trimite confirmare pentru cel de-al doilea segment deci
confirmarea va cuprinde numărul de secvenţă 1025
lungimea antetului - 4 biţi
Specifică dimensiunea antetului ca număr de cuvinte de 32 de biţi (4 octeţi) Antetul
poate avea icircntre 20 şi 60 de octeţi deci valoarea acestui cacircmp va fi icircntre 5 (5 x 4 = 20
octeţi) şi 15 (15 x 4 = 60)
6 biţi rezervaţi pentru utilizări viitoare
6 biţi de control reprezentacircnd următoarele flag-uri ce pot fi setate simultan
o URG - cacircmpul urgent pointer este valid
o ACK - cacircmpul de confirmare este valid
o PSH - destinaţia trebuie să trimită datele către nivelul aplicaţie cacirct mai devreme
o RST - se doreşte resetarea conexiunii
o SYN - iniţierea conexiunii
o FIN - icircnchiderea conexiunii
dimensiunea ferestrei - 16 biţi
Reprezintă numărul de octeţi (icircncepacircnd cu numărul de secvenţă conţinut icircn cacircmpul de
confirmare) pe care destinaţia e dispusă să-l primească Este limitat la 65535 octeţi dar
cu toate că pare o limită destul de mare există situaţii cacircnd se doresc valori mult mai
mari Icircn acest scop se folosesc nişte opţiuni speciale descrise ceva mai tacircrziu care permit
scalarea ferestrei
suma de control - 16 biţi
Această sumă de control acoperă icircntregul segment TCP (atacirct datele cacirct şi antetul TCP) şi
spre deosebire de UDP este obligatoriu să fie completat de transmiţător şi verificat de
receptor Dar ca şi icircn cazul UDP-ului la calculul sumei de control se ia in considerare şi
o zona specială de 12 octeţi ce cuprinde pentru re-verificare cacircmpuri din antetul IP
(adresa IP a sursei şi a destinaţiei)[aici tre sa vina o referire la poza cu pseudo-antetu]
După adăugarea acestui pseudo-antet datele se icircmpart icircn cuvinte de 16 biţi icircn vederea
calculării sumei de control adăugacircndu-se eventual şi un octet de aliniere
urgent pointer - 16 biţi
Este utilizat pentru specificarea deplasamentului ultimului octet de date trimis icircn regim
urgent Astfel ultimul octet din secvenţa urgentă se obţine adunacircnd acest cacircmp la
numărul de secvenţă Ce icircnseamnă acest mod urgent de transmitere există situaţii icircn care
aplicaţiile vor să trimită date `neordonate` Să presupunem că aplicaţia a trimis către
nivelul transport o cantitate mare de date dar la un moment dat observă ceva icircn neregulă
şi doreşte să anuleze operaţia Dacă trimite o comandă de anulare aceasta va fi adăugată
la sfacircrşitul şirului de octeţi deci nu se va putea icircmpiedica ajungerea acestora la nivelul
aplicaţie de la receptor Activacircnd modul urgent datele urgente (comanda de anulare) vor
fi plasate la icircnceputul pachetului Aplicaţiile mai cunoscute care folosesc acest mod sunt
Telnet Rlogin şi FTP
opţiuni - pacircnă la 40 de octeţi (figura 73)
Cele mai utilizate opţiuni sunt
o Sfacircrşit de opţiuni (end of option) - 1 octet
Este utilizat pentru alinierea datelor conţinute icircn cacircmpul de opţiuni Nu poate fi
utilizat decacirct o singură dată marcacircndu-se astfel sfacircrşitul opţiunilor şi icircnceperea
datelor efective Dacă pentru alinierea la un cuvacircnt de 32 de biţi e nevoie de mai
mult de 1 byte se va utiliza opţiunea no operation Orice apare după această
opţiune pacircnă la icircnceputul cuvacircntului următor de 32 de biţi e ignorat
o no operation - 1 octet
Utilizat pentru alinierea la cuvinte de 32 de biţi
o Dimensiunea maximă a segmentului (Maximum Segment Size (MSS)) - 16 biţi
Icircn ciuda denumirii defineşte lungimea maximă a datelor nu dimensiunea
icircntregului segment Poate lua valori icircntre 0 şi 65535 valoarea implicită fiind 536
Această opţiune e valabilă doar icircn pachetele de iniţiere a conexiunii (cele cu flag-
ul SYN setat) fiecare parte făcacircnd cunoscută dimensiunea maximă a datelor
dispusă să le primească icircntr-un pachet Icircn principiu cu cacirct această valoarea e mai
mare e mai bine (deoarece se recuperează din spaţiul ocupat de antetele TCP şi
IP) pacircnă cacircnd apare fragmentarea Valoarea maximă la care se poate seta este
MTU (Maximum Transfer Unit) minus dimensiunea antetului IP şi TCP (1460
octeţi icircn cazul Ethernet)
o Factor de scalare a ferestrei (Window scale factor) - 1 octet
Pentru situaţiile icircn care se doreşte utilizarea unei ferestre mai mare de 65535 bytes
se poate utiliza acest cacircmp pentru mărirea dimensiunii ferestrei Noua dimensiune
va fi Chiar dacă
factorul de scalare poate fi maxim 255 icircn cazul TCPIP el nu poate depăşi
valoarea 16 deoarece dimensiunea maximă a ferestrei nu poate fi mai mare decacirct
valoarea celui mai mare număr de secvenţă ( )
Acest factor se poate seta doar la iniţierea conexiunii Icircn timpul transferului de
date se poate modifica dimensiunea ferestrei dar factorul de scalare rămacircne
acelaşi Dacă cel care a iniţiat conexiunea a trimis icircn segmentul de iniţiere şi acest
factor dar icircn pachetul cu ACK destinatarul nu şi-a trimis şi el factorul atunci se la
considera 0 icircn ambele direcţii Invers dacă cel care solicită deschiderea
conexiunii nu setează factorul destinaţia nu va putea seta factorul de scalare
o Timestamp - 10 octeţi
Utilizat pentru reţinerea timpului icircn vederea calculării RTT (Round Trip Time)
Cacircmpul timestamp e completat de sursă icircn momentul trimiterii segmentului La
destinaţie valoarea este reţinută şi copiată icircn cacircmpul timestamp echo reply al
pachetului cu confirmarea RTT-ul este calculat de sursă făcacircnd diferenţa dintre
timpul curent şi această valoare
Figura Opţiuni TCP
3 Iniţierea şi terminarea unei conexiuni TCP
TCP este un protocol orientat conexiune deci presupune stabilirea unei căi virtuale icircntre sursă şi
destinaţie
Subsections
Protocolul de iniţiere
o 1 Deschiderea simultană
Protocolul de terminare
o 2 Terminarea simultană
o 3 Resetarea conexiunii
Diagrama de stări
Protocolul de iniţiere
Modul de transmisie icircn cazul protocolului TCP este full-duplex deci sunt transmise date
simultan icircn ambele direcţii Aceasta presupune că cel care iniţiază conexiunea trebuie să
primească aprobarea celuilalt capăt icircnainte de icircnceperea transferului de date sursa icircşi anunţă
intenţia de a iniţia o conexiune destinaţia trimite un pachet cu confirmarea cererii şi un pachet de
iniţiere a conexiunii de la el la sursă iar apoi sursa confirmă cererea primită de la destinaţie Paşii
2 şi 3 pot fi realizaţi prin trimiterea unui singur pachet de aceea protocolul de iniţiere este
cunoscut sub numele de three-way handshake
Icircn cadrul protocolului de iniţiere există 2 tipuri de cereri de iniţiere cerere activă (active open)
iniţiată de clientul ce doreşte să stabilească conexiunea cu serverul şi cerere pasivă (passive
open) din partea serverului
Cei 3 paşi sunt
1 Clientul trimite un segment cu flag-ul SYN setat şi care conţine portul sursă portul de la
destinaţie şi numărul de secvenţă generat iniţial (ISN) de la care se vor numerota octeţii
de la client către server Opţional se pot stabili parametrii conexiunii prin setarea lungimii
maxime a segmentelor (MSS) dispus să le primească de la server factorului de scalare a
ferestrei Acest prim segment nu conţine nici un parametru de confirmare şi de asemenea
nu are rost să conţine să seteze dimensiunea ferestrei
2 Al doilea segment e trimis de server şi are un rol dublu confirmă segmentul primit de la
client prin setarea flag-ului ACK şi completează numărul de secvenţă cu numărul de
secvenţă primit plus 1 şi al doilea rol iniţializează conexiunea de la el către client prin
setarea flag-ului SYN şi generarea unui număr de secvenţă iniţial ce va fi folosit icircn
numerotarea octeţilor de la server spre client Pe lacircngă aceasta trebuie să conţină
dimensiunea ferestrei şi opţional poate seta factorul de scalare şi dimensiunea maximă a
segmentului acceptat
3 Clientul trimite un segment cu confirmarea cererii din partea serverului (ACK setat +
completează numărul confirmat cu numărul de secvenţa primit + 1) Ca şi icircn cazul
pasului 2 trebuie să seteze dimensiunea ferestrei Acest pachet poate conţine date
Subsections
1 Deschiderea simultană
1 Deschiderea simultană
Se poate icircntacircmpla ca uneori cele două capete care vor să comunice să icircncerce să stabilească
conexiunea simultan Icircn acest caz după ce fiecare a trimis segmentul de iniţiere (iniţiere activă)
ambele vor trimite un segment cu SYN + ACK şi se va stabili o singură conexiune nu două
Protocolul de terminare
Oricare dintre cele două părţi poate solicita icircnchiderea conexiunii dar conexiunea fiind full-
duplex transferul de date icircn celălalt sens poate continua (această situaţie e denumită half-close)
O icircnchidere completă a unei conexiuni TCP presupune următorii paşi
1 Clientul trimite un segment cu flag-ul FIN activat solicitacircnd icircnchiderea conexiunii
2 Serverul trimite un segment ACK confirmacircnd primirea cererea Numărul de confirmare
se completează normal ca numărul de secvenţă primit + 1
3 Serverul continuă să trimită date către client şi cacircnd doreşte să icircnchidă şi el conexiunea
trimite un segment cu FIN activat
4 Clientul trimite un pachet ACK confirmacircnd icircnchiderea conexiunii
Cel care iniţiază primul procedura de icircnchidere (trimite primul FIN) realizează o icircnchidere activă
(active close) iar celălalt capăt o icircnchidere pasivă (passive close) Icircn mod normal cel care
realizează iniţierea activă va fi primul ce va trimite FIN dar oricare dintre cei doi poate icircnchide
activ conexiunea
Subsections
2 Terminarea simultană
3 Resetarea conexiunii
2 Terminarea simultană
Icircn mod similar cu deschiderea simultană există posibilitatea ca ambele capete ale conexiunii TCP
să iniţieze simultan procedura de icircnchidere a conexiunii Icircn acest caz ambele părţi vor trimite
FIN şi vor aştepta primirea unui ACK Icircn continuare fiecare va primi cererea de terminare şi va
trimite ACK Se observă că numărul de segmente transferate pentru realizarea icircnchiderii
conexiunii (4 segmente) este acelaşi ca la terminarea normală
3 Resetarea conexiunii
Există situaţii icircn care TCP doreşte resetarea conexiunii De exemplu dacă se solicită iniţierea
unei conexiuni la un port inexistent Icircn acest caz cealaltă parte va trimite un segment cu bitul
RST setat pentru a anula solicitarea O altă situaţie este atunci cacircnd se constată că celalalt capăt
al conexiunii nu răspunde un anumit timp (timeout)
Diagrama de stări
Toate evenimentele ce au loc icircn timpul stabilirii conexiunii transferului şi icircnchiderii conexiunii
pot fi rezumate printr-un automat finit cunoscut sub numele de diagrama de stări După cum
chiar numele sugerează este o maşină cu un număr limitat de stări O stare este păstrată pacircnă icircn
momentul apariţiei unui eveniment moment icircn care se poate trece icircn altă stare şisau efectua o
acţiune
Aceste stări posibile sunt (denumirile sunt asemănătoare cu cele utilizate de netstat) cele din
tabelul 71
Tabela Stările diagramei de stări TCP
Stare Descriere
CLOSED Nu există conexiune
LISTEN Serverul aşteaptă cereri de la clienţi
SYN_SENT Cerere de iniţiere (activă) a conexiunii Se
aşteaptă confirmarea
SYN_RCVD S-a primit o cerere de iniţiere conexiune
ESTABLISHED S-a stabilit conexiunea
FIN_WAIT_1 Aplicaţia a solicitat icircnchiderea conexiunii
FIN_WAIT_2 Serverul a acceptat icircnchiderea conexiunii
CLOSING Ambele părţi solicită simultan icircnchiderea
conexiunii
TIME_WAIT Conexiune icircnchisă dar se aşteaptă ca
pachetele retransmise să dispară
CLOSE_WAIT Serverul aşteaptă icircnchiderea dinspre partea
aplicaţiei
LAST_ACK Serverul a icircnchis conexiunea Aşteaptă
ultima confirmare
Icircn diagrama ilustrată icircn figura 74 putem observa 3 tipuri de tranziţii icircntre cele 11 stări tranziţii
ce corespund unei funcţionări normale pentru client (linii normale continue) pentru server (linii
normale icircntrerupte) şi tranziţii pentru situaţii nestandard (linii subţiri continue)
O comportarea normală pentru client presupune parcurgerea următoarelor stări CLOSED
SYN_SEND ESTABLISHED FIN_WAY_1 FIN_WAY_2 TIME_WAIT
Iniţial clientul TCP se află icircn starea CLOSED
Aşteptacircnd icircn starea CLOSED clientul poate primi de la aplicaţie o cerere de iniţiere
activă a unei conexiuni Trimite un segment SYN şi trece icircn starea SYN_SENT
Icircn starea SYN_SENT clientul aşteaptă de la server un segment ACK+SYN după care
trimite un ACK şi trece icircn starea ESTABLISHED Din acest moment poate icircncepe
transferul efectiv de date Clientul va rămacircne icircn această stare cacirct timp are de trimisprimit
date
Aflat icircn această stare clientul TCP poate primi din partea aplicaţiei o cerere de icircnchidere a
conexiunii Icircn acest caz va trimit un segment FIN şi trece icircn starea FIN_WAIT_1
Icircn această stare clientul aşteaptă ACK din partea serverului După ce-l primeşte
conexiunea icircntr-un sens se va icircnchide şi clientul trece icircn starea FIN_WAIT_2
Starea FIN_WAIT_2 durează pacircnă cacircnd primeşte cererea de icircnchidere a conexiunii FIN
din partea serverului Trimite ACK şi va trece icircn starea TIME_WAIT
Icircn această stare se va porni un timer cu valoarea setată la dublul timpului de viaţă estimat
pentru un segment de lungime maximă MSL (Maximum Segment Lifetime) Acest timer
permite retransmiterea ACK-ului icircn cazul icircn care acesta se pierde (celălalt capăt va da
timeout şi va retransmite segmentul FIN) Icircn tot acest time cei doi sockeţi (de la client şi
server) nu vor putea fi reutilizaţi Totodată pachetele icircntacircrziate care sosesc icircn această
perioadă sunt ignorate După expirarea acestui timer clientul revine icircn starea iniţială
CLOSED
Din punctul de vedere al unui server o comportare standard parcurge următoarele stări
CLOSED LISTEN SYN_RCVD ESTABLISHED CLOSE_WAIT şi LAST_ACK
Iniţial serverul TCP se află icircn starea CLOSED
Icircn această stare poate primi de la aplicaţia server o cerere de iniţiere activă şi trece icircn
starea LISTEN
Aflat icircn starea LISTEN serverului TCP poate recepţiona un segment SYN de la un client
TCP Icircn acest caz va trimite ACK+SYN şi va trece icircn starea SYN_RCVD
Icircn această stare serverul aşteaptă primirea confirmării de la client moment icircn care
conexiunea e stabilită icircn ambele sensuri şi se poate icircncepe transferul de date (starea
ESTABLISHED)
Clientul TCP poate solicita icircnchiderea conexiunii trimiţacircnd un segment FIN către server
Icircn acest caz serverul TCP trimite confirmarea şi trece icircn starea CLOSE_WAIT
Icircn această stare serverul aşteaptă să primească din partea programului server icircnchiderea
conexiunii moment icircn care va trimite către client un segment FIN şi trece icircn starea
LAST_ACK
Serverul aşteaptă primirea ultimei confirmări de la client după care revine icircn starea
CLOSED
Atacirct serverul cacirct şi clientul TCP se pot afla icircn oricare din cele 11 stări ale diagramei
Figura Diagrama de stări pentru TCP
4 Controlul fluxului
Dacă icircncă de la icircnceput s-a reuşit stabilirea formatului unui pachet TCP şi a modulului icircn care
trebuie să se facă icircnchiderea şi deschiderea unei conexiuni nu acelaşi lucru se poate spune şi
despre modul icircn care ar trebui să se realizeze controlul fluxului Ţinacircnd seama icircnsă că din 1989
(de cacircnd datează RFC-ul 2581 cel despre care am menţionat că specifică icircn mod clar modul icircn
care trebuie să se comporte o implementare de TCP) TCP-ul a rămas neschimbat putem să icircl
considerăm un rezultat important al domeniului reţelor de calculatoare
Icircn cele ce urmează vom icircnţelege prin controlul fluxului totalitatea algoritmilor care permit
atingerea unei viteze de transfer punct-la-punct cacirct mai mare pentru toate conexiunile existente
Icircn principal aceşti algoritmi stabilesc modul icircn care segmentele şi confirmările trebuie trimise şi
ce acţiuni trebuie executate icircn situaţiile icircn care răspunsurile aşteptate de la celălalt capăt icircntacircrzie
să vină
Subsections
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
Icircntacircrzierea confirmărilor
O modalitate simplă de generare a confirmărilor este de a trimite cacircte una pentru fiecare segment
primit Această politică prezintă avantajul de a face comunicaţia self-clocking icircnsă este
ineficientă dacă segmentele care nu conţin decacirct confirmări sunt urmate la scurtă distanţă (cacircteva
zeci de milisecunde) de segmente ce conţin date efective Pentru a evita această situaţie se
procedează2 la icircntacircrzierea (200ms este o valoare uzuală icircn RFC 1122 se specifică o valoare
maximă de 500ms) a segmentelor care conţin doar confirmări Această strategie face posibil ca
un răspuns generat de primirea unor date să plece sper celălalt capăt icircn acelaşi segment cu
confirmarea
Observaţie deoarece este dificil de menţinut timere pentru fiecare confirmare diferenţa de
200ms este calculată de un timer global Din acest motiv modul efectiv de comportare poate fi
descris şi icircn felul următor cacircnd un segment nu conţine decacirct o confirmare el este pus icircntr-o
coadă ce va fi inspectată de un proces care din 200 icircn 200 ms trimite tot ce s-a acumulat icircn
coada
Footnotes
2
Acest comportament a fost propus de David D Clark icircn iulie 1982 icircn RFC 813
Algoritmul Nagle
Acest algoritm3 icircncearcă să icircmbunătăţească performanţele exploatacircnd următoarea caracteristică
foarte des icircntacirclnită icircn dialogul dintre două staţii dacă se icircncearcă trimiterea unor date de
dimensiune mică icircnsă există icircncă date neconfirmate de partener atunci ele sunt buffer-ate şi
trimise icircntr-un segment mai mare cacircnd soseşte confirmarea aşteptată Icircn acest fel se poate evita
generarea datagramelor mici (tinygrame) icircn situaţia unei legături lente Icircn cazul unei legături
rapide confirmările vor veni repede şi icircntacircrzierea introdusă de algoritm va neglijabilă
Există icircnsă şi cazuri icircn care acest algoritm duce la deprecierea performanţelor mesajele scurte
generate de mişcările mouse-ului icircn cazul folosirii unui server X Window sau utilizarea tastelor
care trimit mai mult de un caracter (secvenţe escape) Pentru a rezolva aceste inconveninte API-
ul de utilizare a TCP-ului trebuie să ofere o modalitate de a dezactiva acest algoritm (icircn sistemele
bazate pe sockeţi există icircn acest scop opţiunea TCP_NODELAY)
Footnotes
algoritm3
Algoritmul aparţinacircnd lui John Nagle a fost propus icircn ianuarie 1984 icircn RFC 896
Fereastra glisantă
Algoritmul implementat de TCP pentru a implementa transferul sigur de date este cunoscut icircn
teorie sub numele de Go-Back-N Icircn acest algoritm se utilizează numere de secvenţă pentru a
distinge pachetele icircntre ele şi o coadă (dimensiunea maximă a cozii reprezintă fereastra) de
pachetele a căror confirmare se aşteaptă Pachetele se icircmpart icircn 4 categorii
1 pachete trimis şi pentru care s-a primit confirmare
2 pachete trimise şi pentru care se aşteaptă icircncă confirmarea
3 pachete care nu au fost trimise icircncă dar care nu depăşesc limitele ferestrei şi deci pot fi
trimise
4 pachete care icircncă nu au fost trimite şi care nici nu vor putea fi trimise decacirct după ce au
fost trimise toate pachetele din categoria 3 şi s-au primit o parte din confirmările la
pachetele din categoria 2
Dacă confirmările pentru pachetele din categoria 2 icircntacircrzie prea mult (un mecanism de timer-e
informează asupra acestui lucru) atunci ele vor fi retrimise Icircn versiunea iniţială TCP-ul nu
permitea decacirct confirmări pozitive ceea ce icircnseamnă că avansarea ferestrei se va icircmpotmoli la
segmentele neconfirmate Cum se poate evita aceasta situaţie vom discuta icircn detaliu icircn capitolele
următoare O soluţie foarte radicală o constituie introducerea de confirmări selective (acest lucru
este realizat de RFC 2018 din octombrie 1996) Această modifică face ca TCP-ul actual să fie un
hibrid de Go-Back-N şi Selective Repeat
Deoarece dimensiunea ferestrei este anunţată la fiecare segment un client lent poate ca pe măsură
ce trimite confirmările să informeze despre progresul icircnregistrat la livrarea datelor următorului
nivel (aplicaţie) Dacă datele vin prea repede pentru viteza cu care clientul procesează datele
fereastra fereastra se va dimiua şi chiar icircnchide (acest lucru se realizează anunţacircnd o fereastră de
dimensiune zero) Cum se realizează efectiv redeschiderea vom analiza icircntr-un capitol viitor
Slow start
Un transfer de date TCP poate să icircnceapă prin transmiterea de segmente pacircnă la umplerea
icircntregii ferestre după care fie se primesc confirmări care vor permite unor noi pachete să fie
trimise fie vor expira timer-ele de retransmisie şi se va icircncepe retrimiterea pachetelor de la
icircnceputul ferestrei Din păcate un astfel de comportament poate duce la pomparea icircn reţea a unui
număr de pachete prea mare pentru capacitatea disponibilă efectiv icircnrăutăţind congestia Pentru
a evita acest lucru s-a propus următoarea soluţie4 iniţial se trimite un segment după primirea
confirmării lui se trimit două segmente după sosirea confirmărilor pentru ele se trimit patru
segmente şi aşa mai departe La un moment dat fie vor icircncepe să se piardă segmente (un indiciu
că s-a atins capacitatea maximă a canalului) fie se va umple fereastra pe care o anunţă cel care
primeşte Trebuie să remarcam că datorită creşterii exponenţiale a numărului de segmente se va
atinge destul de repede una din cele două situaţii
Modalitatea efectivă de implementare a acestui algoritm are la bază utilizarea unei ferestre de
congestie (congestion window cwnd) care este iniţializată cu dimensiunea unui segment (cwnd
se calculează icircn octeţi) şi la fiecare pas este dublată fereastra efectivă din cadrul căreia se pot
trimite segmente este dată de minimul dintre ultima fereastra comunicată de partener şi cwnd
Footnotes
soluţie4
Soluţia aparţine lui V Jacobson şi a fost prezentată icircn 1988 la conferinţă ACM
SIGCOMM-88
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Deoarece TCP trebuie să funcţioneze icircn condiţii variate de latenţă modul icircn care se face
retransmiterea trebuie să fie cacirct mai flexibil (şi simplu icircn acelaşi timp pentru a introduce un
overhead cacirct mai mic) Timpul cacirct se aşteaptă venirea unei confirmări (retransmission timeout
RTO) este calculat prin cronometrarea timpului care icirci ia unui segment trimis să fie confirmat
Pentru o anumită conexiune se cronometrează cacircte un singur segment la un moment dat iar pe
baza RTT-ului măsurat se actualizează valoare RTO-ului
Icircn RFC 793 formula de calcul a RTO-ului este următoarea
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
1 UDP
Subsections
1 Caracteristici UDP
2 Formatul pachetelor UDP
1 Caracteristici UDP
UDP (User Datagram Protocol) este un protocol de nivel transport construit special pentru a oferi
un serviciu de comunicare cacirct mai simplu peste IP Specificaţiile protocolului au fost publicate icircn
1980 icircn RFC-ul cu numărul 7681
Cacircteva caracteristici ale UDP-ului sunt
este un serviciu de tip datagramă cererile de trimitere de date primite de la nivelul
superior sunt tratate independent
comunicarea are loc fără stabilirea unei legături (conection-less) nu există mecanisme de
stabilire şi terminare a unei conexiuni deoarece toate datele sunt trimise icircn cadrul unui
singur pachet IP care eventual va fi supus fragmentării
nu se garantează ajungerea ala destinaţie a datelor (best effort) ajungerea la destinaţie nu
este anunţată sursei
datele transportate sunt protejate de o sumă de control (introdusă ca opţională iniţial ea
este trecută ca necesară(must) icircn RFC 1122 care stabileşte modul de comportare al
clienţilor icircn Internet)
overhead-ul introdus este minim doar 8 octeţi
Cacircteva utilizări tipice ale UDP-ului
servicii de rezolvare a numelor (DNS) deoarece icircntrebările şi răspunsurile 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 fişiere (NFS) deoarece acest tip de aplicaţii sunt icircn general rulate icircn reţele
locale cu performanţe ridicate care nu necesită mecanismele TCP
managementul reţelei (SNMP)
protocoale de rutare (RIP)
Footnotes
7681
RFC 768 are nici mai mult nici mai puţin decacirct 3 pagini nu conţine cuprins dar are o listă
de 5 referinţe bibliografice
2 Formatul pachetelor UDP
Datagramele UDP sunt formate dintr-un antet (figura 71) urmat de datele care se doresc
transmise (dacă există)
Figura 71 Structura unei datagrame UDP
Antetul cuprinde
port sursă - 16 biţi
Icircmpreună cu adresa IP a sursei acest număr identifică icircn mod unic locul de unde a fost
trimis datagrama UDP
port destinaţie - 16 biţi
Icircmpreună cu adresa IP a destinaţiei acest număr identifică icircn mod unic destinaţia dorită
pentru datagrama UDP
lungimea pachetului UDP - 16 biţi
Lungimea minimă măsoară datagrama UDP cu tot cu antent şi prin urmare are o valoare
minimă de 8 octeţi
sumă de control - 16 biţi
Suma de control acoperă icircntreg pachetul UDP cacirct şi un pseudo antet de 12 octeţi format
din
adresa IP a sursei - 32 biţi
o adresa IP a destinaţiei - 32 biţi
8 biţi de zero pentru aliniere
numărul protocolului UDP (17) reprezentat pe 8 biţi
lungimea pachetului UDP - 16 biţi
Deoarece suma de control necesită icircn calculul ei un număr multiplu de 16 octeţi la
sfacircrşitul datelor se adaugă un număr potrivit de octeţi de zero Dacă suma este 0 atunci ea
va fi stocată ca 65535 (toţi biţii pe 1) Un 0 icircn cacircmpul de sumei de control indică faptul
că suma de control nu a fost calculată Observaţie chiar dacă un client are inhibat (icircn
mod explicit) calcului sumei de control el este obligat să verifice suma pachetelor care
sosesc şi au suma calculată
2 TCP
Subsections
1 Caracteristici TCP
2 Formatul pachetelor TCP
3 Iniţierea şi terminarea unei conexiuni TCP
o Protocolul de iniţiere
1 Deschiderea simultană
o Protocolul de terminare
2 Terminarea simultană
3 Resetarea conexiunii
o Diagrama de stări
4 Controlul fluxului
o Icircntacircrzierea confirmărilor
o Algoritmul Nagle
o Fereastra glisantă
o Slow start
o Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
o Evitarea congestiei
o Fast Retransmission Fast Recovery
o Sindromul ``Silly Window
o TCP Keepalive Timer
1 Caracteristici TCP
Deoarece protocolul IP este de tip datagramă utilizarea lui direct icircn aplicaţii care in general au
nevoie de conexiuni sigure este mult prea anevoioasă Din aceste motive peste IP a fost construit
un alt protocol TCP (transimission control protocol) care corectează aceste probleme Prima
definire se găseşte icircn RFC-ul cu numărul 793 şi datează din septembrie 1981 Din cauza deselor
congestii apărute icircn 1986 algoritmul care stă la baza TCP-ului este reanalizat şi icircn octombrie
1989 icircn RFC-ul cu numărul 1122 este publicată o nouă specificare mult mai eficientă şi
neambiguă a TCP-ului Noi probleme legate de viteze mari sunt tratate icircn RFC-ul 1323 iar icircn
2018 TCP-ul este extins pentru a permite confirmările selective (selective acknowledge) Seria
de RFC-urie fundamentale este icircncheiată de apariţia icircn 1989 a RFC-ului cu numărul 2581 Icircn el
se specifică foarte strict comportamentul care este permis pentru o implementare de TCP
Alături de protocolul UDP TCP se situează pe nivelul transport icircn ierarhia de protocoale deci
icircntre nivelul aplicaţie şi nivelul reţea Dar cu toate că se bazează pe acelaşi protocol (IP) ca şi
UDP TCP furnizează către nivelul aplicaţie cu totul alt tip de servicii servicii orientate-
conexiune sigure de tip flux de octeţi
Termenul de orientat-conexiune presupune că icircntre cele două aplicaţii care comunică utilizacircnd
TCP trebuie să se stabilească o conexiune TCP icircnainte ca transferul de date să aibă loc Această
conexiune nu este efectiv una fizică ci virtuală asemănător cum se icircntacircmplă icircn sistemul de
telefonie clasică cineva formează un număr şi abia icircn momentul icircn care cealaltă persoană
răspunde se poate icircncepe conversaţia Fiind o conexiune host-la-host nu există noţiunile de
broadcast sau multicast
Transferul sigur de date este asigurat icircn următorul mod
Datele sunt icircmpărţite icircn bucăţi a căror dimensiune optimă e determinată de TCP spre
deosebire de UDP care trimite datagrame UDP corespunzătoare cu dimensiunea datelor
primite de la nivelul aplicaţie Unitatea de date trimisă de TCP către nivelul reţea poartă
numele de segment
Cacircnd TCP trimite un segment porneşte un timer şi dacă nu se primeşte confirmarea
segmentului respectiv icircntr-un anumit timp icircl retransmite
Icircn momentul icircn care se primeşte un segment TCP trimite o confirmare (din motive de
eficienţă aceasta poate fi amacircnată un anumit interval de timp)
Icircn headerul TCP este menţinută o sumă de control pentru detectarea modificărilor icircn date
Dacă se recepţionează un segment corupt TCP icircl ignoră urmacircnd să fie retransmis datorită
neprimirii confirmării
Deoarece segmentele TCP sunt transmise mai departe icircncapsulate icircn datagrame IP iar
acestea pot ajunge icircn orice ordine segmentele TCP pot ajunge icircn altă ordine decacirct cea icircn
care au fost trimise De aceea la destinaţie TCP-ul trebuie să se folosească de numere de
secvenţă pentru a reordona eventual segmentele icircnainte de a le livra către nivelul
aplicaţie De asemenea TCP trebuie să asigure ignorarea duplicatelor
TCP asigură controlul fluxului icircn condiţiile icircn care viteza de trimitere a datelor de la sursă
poate fi mult prea mare decacirct capacitatea de prelucrare de la destinaţie
Serviciul oferit de TCP este de tip flux de octeţi deoarece oferă garanţii că fluxul de date trimis
de sursă va fi livrat fără modificări la destinaţie Comparativ UDP-ul produce pentru fiecare
transfer cerut de nivelul aplicaţie un pachet IP (care ulterior poate fi supus fragmentării) care
dacă ajunge la destinaţie corect va fi livrat direct nivelului aplicaţie fără a garanta icircn vreun fel
ordinea
2 Formatul pachetelor TCP
Pachetele de date transmise de TCP segmentele sunt formate dintr-un antet (figura 72) de 20
octeţi urmat de datele primite de la nivelul aplicaţie Antetul poate uneori conţine şi o serie de
opţiuni caz icircn care poate ajunge la 60 octeţi
Figura 72 Structura unui segment TCP
Antetul unui segment TCP cuprinde
port sursă - 16 biţi pentru specificarea portului aplicaţiei transmiţătoare
port destinaţie - 16 biţi pentru specificarea portului aplicaţiei ce recepţionează segmentul
TCP
Aceste două porturi icircmpreună cu adresele ale sursei şi destinaţiei conţinute icircn antet-ul IP
identifică icircn mod unic conexiunea Pentru o pereche formată dintr-o adresă IP şi un port
se foloseşte adesea denumirea de socket (denumire introdusă icircn specificaţiile iniţiale ale
protocolului TCP icircn RFC 793)
număr de secvenţă - 32 biţi
Pentru a asigura un serviciu de tip flux de octeţi TCP numerotează fiecare octet de date
utilizacircnd un număr de secvenţă Numărul de secvenţă din cadrul antetului TCP specifică
destinaţiei care este primul octet din fluxul trimis La iniţierea unei conexiuni se setează
flag-ul SYN şi se alege aleator un număr de secvenţă de icircnceput utilizacircnd un generator de
numere de secvenţă ISN (Initial sequence number) Numărul de secvenţă al primului
octet de date va fi numărul generat ISN plus 1 deoarece pachetul de iniţiere (cu SYN
setat) consumă şi el un număr de secvenţă Se va vedea mai departe că şi flag-ul de
terminare a conexiunii FIN consumă şi el un număr de secvenţă
confirmare - 32 biţi
Reprezintă numărul de secvenţă al octetului de date pe care transmiţătorul confirmării se
aşteaptă să-l primească Astfel dacă s-a recepţionat octetul cu numărul de secvenţă x (icircn
numerotaţia sursei) pachetul de confirmare va avea flag-ul ACK setat şi va conţine
numărul de confirmare x + 1 Trimiterea unui ACK nu consumă un număr de secvenţă
deoarece atacirct acest cacircmp cacirct şi flag-ul ACK fac parte din antet şi după stabilirea
conexiunii ambele cacircmpuri devin active Acest mecanism nu permite confirmări selective
pentru că numărul de secvenţă specifică pacircnă unde s-au recepţionat date De exemplu
dacă la destinaţie au ajuns octeţii 1-1024 şi următorul segment primit conţine octeţii
2049-3072 nu se poate trimite confirmare pentru cel de-al doilea segment deci
confirmarea va cuprinde numărul de secvenţă 1025
lungimea antetului - 4 biţi
Specifică dimensiunea antetului ca număr de cuvinte de 32 de biţi (4 octeţi) Antetul
poate avea icircntre 20 şi 60 de octeţi deci valoarea acestui cacircmp va fi icircntre 5 (5 x 4 = 20
octeţi) şi 15 (15 x 4 = 60)
6 biţi rezervaţi pentru utilizări viitoare
6 biţi de control reprezentacircnd următoarele flag-uri ce pot fi setate simultan
o URG - cacircmpul urgent pointer este valid
o ACK - cacircmpul de confirmare este valid
o PSH - destinaţia trebuie să trimită datele către nivelul aplicaţie cacirct mai devreme
o RST - se doreşte resetarea conexiunii
o SYN - iniţierea conexiunii
o FIN - icircnchiderea conexiunii
dimensiunea ferestrei - 16 biţi
Reprezintă numărul de octeţi (icircncepacircnd cu numărul de secvenţă conţinut icircn cacircmpul de
confirmare) pe care destinaţia e dispusă să-l primească Este limitat la 65535 octeţi dar
cu toate că pare o limită destul de mare există situaţii cacircnd se doresc valori mult mai
mari Icircn acest scop se folosesc nişte opţiuni speciale descrise ceva mai tacircrziu care permit
scalarea ferestrei
suma de control - 16 biţi
Această sumă de control acoperă icircntregul segment TCP (atacirct datele cacirct şi antetul TCP) şi
spre deosebire de UDP este obligatoriu să fie completat de transmiţător şi verificat de
receptor Dar ca şi icircn cazul UDP-ului la calculul sumei de control se ia in considerare şi
o zona specială de 12 octeţi ce cuprinde pentru re-verificare cacircmpuri din antetul IP
(adresa IP a sursei şi a destinaţiei)[aici tre sa vina o referire la poza cu pseudo-antetu]
După adăugarea acestui pseudo-antet datele se icircmpart icircn cuvinte de 16 biţi icircn vederea
calculării sumei de control adăugacircndu-se eventual şi un octet de aliniere
urgent pointer - 16 biţi
Este utilizat pentru specificarea deplasamentului ultimului octet de date trimis icircn regim
urgent Astfel ultimul octet din secvenţa urgentă se obţine adunacircnd acest cacircmp la
numărul de secvenţă Ce icircnseamnă acest mod urgent de transmitere există situaţii icircn care
aplicaţiile vor să trimită date `neordonate` Să presupunem că aplicaţia a trimis către
nivelul transport o cantitate mare de date dar la un moment dat observă ceva icircn neregulă
şi doreşte să anuleze operaţia Dacă trimite o comandă de anulare aceasta va fi adăugată
la sfacircrşitul şirului de octeţi deci nu se va putea icircmpiedica ajungerea acestora la nivelul
aplicaţie de la receptor Activacircnd modul urgent datele urgente (comanda de anulare) vor
fi plasate la icircnceputul pachetului Aplicaţiile mai cunoscute care folosesc acest mod sunt
Telnet Rlogin şi FTP
opţiuni - pacircnă la 40 de octeţi (figura 73)
Cele mai utilizate opţiuni sunt
o Sfacircrşit de opţiuni (end of option) - 1 octet
Este utilizat pentru alinierea datelor conţinute icircn cacircmpul de opţiuni Nu poate fi
utilizat decacirct o singură dată marcacircndu-se astfel sfacircrşitul opţiunilor şi icircnceperea
datelor efective Dacă pentru alinierea la un cuvacircnt de 32 de biţi e nevoie de mai
mult de 1 byte se va utiliza opţiunea no operation Orice apare după această
opţiune pacircnă la icircnceputul cuvacircntului următor de 32 de biţi e ignorat
o no operation - 1 octet
Utilizat pentru alinierea la cuvinte de 32 de biţi
o Dimensiunea maximă a segmentului (Maximum Segment Size (MSS)) - 16 biţi
Icircn ciuda denumirii defineşte lungimea maximă a datelor nu dimensiunea
icircntregului segment Poate lua valori icircntre 0 şi 65535 valoarea implicită fiind 536
Această opţiune e valabilă doar icircn pachetele de iniţiere a conexiunii (cele cu flag-
ul SYN setat) fiecare parte făcacircnd cunoscută dimensiunea maximă a datelor
dispusă să le primească icircntr-un pachet Icircn principiu cu cacirct această valoarea e mai
mare e mai bine (deoarece se recuperează din spaţiul ocupat de antetele TCP şi
IP) pacircnă cacircnd apare fragmentarea Valoarea maximă la care se poate seta este
MTU (Maximum Transfer Unit) minus dimensiunea antetului IP şi TCP (1460
octeţi icircn cazul Ethernet)
o Factor de scalare a ferestrei (Window scale factor) - 1 octet
Pentru situaţiile icircn care se doreşte utilizarea unei ferestre mai mare de 65535 bytes
se poate utiliza acest cacircmp pentru mărirea dimensiunii ferestrei Noua dimensiune
va fi Chiar dacă
factorul de scalare poate fi maxim 255 icircn cazul TCPIP el nu poate depăşi
valoarea 16 deoarece dimensiunea maximă a ferestrei nu poate fi mai mare decacirct
valoarea celui mai mare număr de secvenţă ( )
Acest factor se poate seta doar la iniţierea conexiunii Icircn timpul transferului de
date se poate modifica dimensiunea ferestrei dar factorul de scalare rămacircne
acelaşi Dacă cel care a iniţiat conexiunea a trimis icircn segmentul de iniţiere şi acest
factor dar icircn pachetul cu ACK destinatarul nu şi-a trimis şi el factorul atunci se la
considera 0 icircn ambele direcţii Invers dacă cel care solicită deschiderea
conexiunii nu setează factorul destinaţia nu va putea seta factorul de scalare
o Timestamp - 10 octeţi
Utilizat pentru reţinerea timpului icircn vederea calculării RTT (Round Trip Time)
Cacircmpul timestamp e completat de sursă icircn momentul trimiterii segmentului La
destinaţie valoarea este reţinută şi copiată icircn cacircmpul timestamp echo reply al
pachetului cu confirmarea RTT-ul este calculat de sursă făcacircnd diferenţa dintre
timpul curent şi această valoare
Figura Opţiuni TCP
3 Iniţierea şi terminarea unei conexiuni TCP
TCP este un protocol orientat conexiune deci presupune stabilirea unei căi virtuale icircntre sursă şi
destinaţie
Subsections
Protocolul de iniţiere
o 1 Deschiderea simultană
Protocolul de terminare
o 2 Terminarea simultană
o 3 Resetarea conexiunii
Diagrama de stări
Protocolul de iniţiere
Modul de transmisie icircn cazul protocolului TCP este full-duplex deci sunt transmise date
simultan icircn ambele direcţii Aceasta presupune că cel care iniţiază conexiunea trebuie să
primească aprobarea celuilalt capăt icircnainte de icircnceperea transferului de date sursa icircşi anunţă
intenţia de a iniţia o conexiune destinaţia trimite un pachet cu confirmarea cererii şi un pachet de
iniţiere a conexiunii de la el la sursă iar apoi sursa confirmă cererea primită de la destinaţie Paşii
2 şi 3 pot fi realizaţi prin trimiterea unui singur pachet de aceea protocolul de iniţiere este
cunoscut sub numele de three-way handshake
Icircn cadrul protocolului de iniţiere există 2 tipuri de cereri de iniţiere cerere activă (active open)
iniţiată de clientul ce doreşte să stabilească conexiunea cu serverul şi cerere pasivă (passive
open) din partea serverului
Cei 3 paşi sunt
1 Clientul trimite un segment cu flag-ul SYN setat şi care conţine portul sursă portul de la
destinaţie şi numărul de secvenţă generat iniţial (ISN) de la care se vor numerota octeţii
de la client către server Opţional se pot stabili parametrii conexiunii prin setarea lungimii
maxime a segmentelor (MSS) dispus să le primească de la server factorului de scalare a
ferestrei Acest prim segment nu conţine nici un parametru de confirmare şi de asemenea
nu are rost să conţine să seteze dimensiunea ferestrei
2 Al doilea segment e trimis de server şi are un rol dublu confirmă segmentul primit de la
client prin setarea flag-ului ACK şi completează numărul de secvenţă cu numărul de
secvenţă primit plus 1 şi al doilea rol iniţializează conexiunea de la el către client prin
setarea flag-ului SYN şi generarea unui număr de secvenţă iniţial ce va fi folosit icircn
numerotarea octeţilor de la server spre client Pe lacircngă aceasta trebuie să conţină
dimensiunea ferestrei şi opţional poate seta factorul de scalare şi dimensiunea maximă a
segmentului acceptat
3 Clientul trimite un segment cu confirmarea cererii din partea serverului (ACK setat +
completează numărul confirmat cu numărul de secvenţa primit + 1) Ca şi icircn cazul
pasului 2 trebuie să seteze dimensiunea ferestrei Acest pachet poate conţine date
Subsections
1 Deschiderea simultană
1 Deschiderea simultană
Se poate icircntacircmpla ca uneori cele două capete care vor să comunice să icircncerce să stabilească
conexiunea simultan Icircn acest caz după ce fiecare a trimis segmentul de iniţiere (iniţiere activă)
ambele vor trimite un segment cu SYN + ACK şi se va stabili o singură conexiune nu două
Protocolul de terminare
Oricare dintre cele două părţi poate solicita icircnchiderea conexiunii dar conexiunea fiind full-
duplex transferul de date icircn celălalt sens poate continua (această situaţie e denumită half-close)
O icircnchidere completă a unei conexiuni TCP presupune următorii paşi
1 Clientul trimite un segment cu flag-ul FIN activat solicitacircnd icircnchiderea conexiunii
2 Serverul trimite un segment ACK confirmacircnd primirea cererea Numărul de confirmare
se completează normal ca numărul de secvenţă primit + 1
3 Serverul continuă să trimită date către client şi cacircnd doreşte să icircnchidă şi el conexiunea
trimite un segment cu FIN activat
4 Clientul trimite un pachet ACK confirmacircnd icircnchiderea conexiunii
Cel care iniţiază primul procedura de icircnchidere (trimite primul FIN) realizează o icircnchidere activă
(active close) iar celălalt capăt o icircnchidere pasivă (passive close) Icircn mod normal cel care
realizează iniţierea activă va fi primul ce va trimite FIN dar oricare dintre cei doi poate icircnchide
activ conexiunea
Subsections
2 Terminarea simultană
3 Resetarea conexiunii
2 Terminarea simultană
Icircn mod similar cu deschiderea simultană există posibilitatea ca ambele capete ale conexiunii TCP
să iniţieze simultan procedura de icircnchidere a conexiunii Icircn acest caz ambele părţi vor trimite
FIN şi vor aştepta primirea unui ACK Icircn continuare fiecare va primi cererea de terminare şi va
trimite ACK Se observă că numărul de segmente transferate pentru realizarea icircnchiderii
conexiunii (4 segmente) este acelaşi ca la terminarea normală
3 Resetarea conexiunii
Există situaţii icircn care TCP doreşte resetarea conexiunii De exemplu dacă se solicită iniţierea
unei conexiuni la un port inexistent Icircn acest caz cealaltă parte va trimite un segment cu bitul
RST setat pentru a anula solicitarea O altă situaţie este atunci cacircnd se constată că celalalt capăt
al conexiunii nu răspunde un anumit timp (timeout)
Diagrama de stări
Toate evenimentele ce au loc icircn timpul stabilirii conexiunii transferului şi icircnchiderii conexiunii
pot fi rezumate printr-un automat finit cunoscut sub numele de diagrama de stări După cum
chiar numele sugerează este o maşină cu un număr limitat de stări O stare este păstrată pacircnă icircn
momentul apariţiei unui eveniment moment icircn care se poate trece icircn altă stare şisau efectua o
acţiune
Aceste stări posibile sunt (denumirile sunt asemănătoare cu cele utilizate de netstat) cele din
tabelul 71
Tabela Stările diagramei de stări TCP
Stare Descriere
CLOSED Nu există conexiune
LISTEN Serverul aşteaptă cereri de la clienţi
SYN_SENT Cerere de iniţiere (activă) a conexiunii Se
aşteaptă confirmarea
SYN_RCVD S-a primit o cerere de iniţiere conexiune
ESTABLISHED S-a stabilit conexiunea
FIN_WAIT_1 Aplicaţia a solicitat icircnchiderea conexiunii
FIN_WAIT_2 Serverul a acceptat icircnchiderea conexiunii
CLOSING Ambele părţi solicită simultan icircnchiderea
conexiunii
TIME_WAIT Conexiune icircnchisă dar se aşteaptă ca
pachetele retransmise să dispară
CLOSE_WAIT Serverul aşteaptă icircnchiderea dinspre partea
aplicaţiei
LAST_ACK Serverul a icircnchis conexiunea Aşteaptă
ultima confirmare
Icircn diagrama ilustrată icircn figura 74 putem observa 3 tipuri de tranziţii icircntre cele 11 stări tranziţii
ce corespund unei funcţionări normale pentru client (linii normale continue) pentru server (linii
normale icircntrerupte) şi tranziţii pentru situaţii nestandard (linii subţiri continue)
O comportarea normală pentru client presupune parcurgerea următoarelor stări CLOSED
SYN_SEND ESTABLISHED FIN_WAY_1 FIN_WAY_2 TIME_WAIT
Iniţial clientul TCP se află icircn starea CLOSED
Aşteptacircnd icircn starea CLOSED clientul poate primi de la aplicaţie o cerere de iniţiere
activă a unei conexiuni Trimite un segment SYN şi trece icircn starea SYN_SENT
Icircn starea SYN_SENT clientul aşteaptă de la server un segment ACK+SYN după care
trimite un ACK şi trece icircn starea ESTABLISHED Din acest moment poate icircncepe
transferul efectiv de date Clientul va rămacircne icircn această stare cacirct timp are de trimisprimit
date
Aflat icircn această stare clientul TCP poate primi din partea aplicaţiei o cerere de icircnchidere a
conexiunii Icircn acest caz va trimit un segment FIN şi trece icircn starea FIN_WAIT_1
Icircn această stare clientul aşteaptă ACK din partea serverului După ce-l primeşte
conexiunea icircntr-un sens se va icircnchide şi clientul trece icircn starea FIN_WAIT_2
Starea FIN_WAIT_2 durează pacircnă cacircnd primeşte cererea de icircnchidere a conexiunii FIN
din partea serverului Trimite ACK şi va trece icircn starea TIME_WAIT
Icircn această stare se va porni un timer cu valoarea setată la dublul timpului de viaţă estimat
pentru un segment de lungime maximă MSL (Maximum Segment Lifetime) Acest timer
permite retransmiterea ACK-ului icircn cazul icircn care acesta se pierde (celălalt capăt va da
timeout şi va retransmite segmentul FIN) Icircn tot acest time cei doi sockeţi (de la client şi
server) nu vor putea fi reutilizaţi Totodată pachetele icircntacircrziate care sosesc icircn această
perioadă sunt ignorate După expirarea acestui timer clientul revine icircn starea iniţială
CLOSED
Din punctul de vedere al unui server o comportare standard parcurge următoarele stări
CLOSED LISTEN SYN_RCVD ESTABLISHED CLOSE_WAIT şi LAST_ACK
Iniţial serverul TCP se află icircn starea CLOSED
Icircn această stare poate primi de la aplicaţia server o cerere de iniţiere activă şi trece icircn
starea LISTEN
Aflat icircn starea LISTEN serverului TCP poate recepţiona un segment SYN de la un client
TCP Icircn acest caz va trimite ACK+SYN şi va trece icircn starea SYN_RCVD
Icircn această stare serverul aşteaptă primirea confirmării de la client moment icircn care
conexiunea e stabilită icircn ambele sensuri şi se poate icircncepe transferul de date (starea
ESTABLISHED)
Clientul TCP poate solicita icircnchiderea conexiunii trimiţacircnd un segment FIN către server
Icircn acest caz serverul TCP trimite confirmarea şi trece icircn starea CLOSE_WAIT
Icircn această stare serverul aşteaptă să primească din partea programului server icircnchiderea
conexiunii moment icircn care va trimite către client un segment FIN şi trece icircn starea
LAST_ACK
Serverul aşteaptă primirea ultimei confirmări de la client după care revine icircn starea
CLOSED
Atacirct serverul cacirct şi clientul TCP se pot afla icircn oricare din cele 11 stări ale diagramei
Figura Diagrama de stări pentru TCP
4 Controlul fluxului
Dacă icircncă de la icircnceput s-a reuşit stabilirea formatului unui pachet TCP şi a modulului icircn care
trebuie să se facă icircnchiderea şi deschiderea unei conexiuni nu acelaşi lucru se poate spune şi
despre modul icircn care ar trebui să se realizeze controlul fluxului Ţinacircnd seama icircnsă că din 1989
(de cacircnd datează RFC-ul 2581 cel despre care am menţionat că specifică icircn mod clar modul icircn
care trebuie să se comporte o implementare de TCP) TCP-ul a rămas neschimbat putem să icircl
considerăm un rezultat important al domeniului reţelor de calculatoare
Icircn cele ce urmează vom icircnţelege prin controlul fluxului totalitatea algoritmilor care permit
atingerea unei viteze de transfer punct-la-punct cacirct mai mare pentru toate conexiunile existente
Icircn principal aceşti algoritmi stabilesc modul icircn care segmentele şi confirmările trebuie trimise şi
ce acţiuni trebuie executate icircn situaţiile icircn care răspunsurile aşteptate de la celălalt capăt icircntacircrzie
să vină
Subsections
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
Icircntacircrzierea confirmărilor
O modalitate simplă de generare a confirmărilor este de a trimite cacircte una pentru fiecare segment
primit Această politică prezintă avantajul de a face comunicaţia self-clocking icircnsă este
ineficientă dacă segmentele care nu conţin decacirct confirmări sunt urmate la scurtă distanţă (cacircteva
zeci de milisecunde) de segmente ce conţin date efective Pentru a evita această situaţie se
procedează2 la icircntacircrzierea (200ms este o valoare uzuală icircn RFC 1122 se specifică o valoare
maximă de 500ms) a segmentelor care conţin doar confirmări Această strategie face posibil ca
un răspuns generat de primirea unor date să plece sper celălalt capăt icircn acelaşi segment cu
confirmarea
Observaţie deoarece este dificil de menţinut timere pentru fiecare confirmare diferenţa de
200ms este calculată de un timer global Din acest motiv modul efectiv de comportare poate fi
descris şi icircn felul următor cacircnd un segment nu conţine decacirct o confirmare el este pus icircntr-o
coadă ce va fi inspectată de un proces care din 200 icircn 200 ms trimite tot ce s-a acumulat icircn
coada
Footnotes
2
Acest comportament a fost propus de David D Clark icircn iulie 1982 icircn RFC 813
Algoritmul Nagle
Acest algoritm3 icircncearcă să icircmbunătăţească performanţele exploatacircnd următoarea caracteristică
foarte des icircntacirclnită icircn dialogul dintre două staţii dacă se icircncearcă trimiterea unor date de
dimensiune mică icircnsă există icircncă date neconfirmate de partener atunci ele sunt buffer-ate şi
trimise icircntr-un segment mai mare cacircnd soseşte confirmarea aşteptată Icircn acest fel se poate evita
generarea datagramelor mici (tinygrame) icircn situaţia unei legături lente Icircn cazul unei legături
rapide confirmările vor veni repede şi icircntacircrzierea introdusă de algoritm va neglijabilă
Există icircnsă şi cazuri icircn care acest algoritm duce la deprecierea performanţelor mesajele scurte
generate de mişcările mouse-ului icircn cazul folosirii unui server X Window sau utilizarea tastelor
care trimit mai mult de un caracter (secvenţe escape) Pentru a rezolva aceste inconveninte API-
ul de utilizare a TCP-ului trebuie să ofere o modalitate de a dezactiva acest algoritm (icircn sistemele
bazate pe sockeţi există icircn acest scop opţiunea TCP_NODELAY)
Footnotes
algoritm3
Algoritmul aparţinacircnd lui John Nagle a fost propus icircn ianuarie 1984 icircn RFC 896
Fereastra glisantă
Algoritmul implementat de TCP pentru a implementa transferul sigur de date este cunoscut icircn
teorie sub numele de Go-Back-N Icircn acest algoritm se utilizează numere de secvenţă pentru a
distinge pachetele icircntre ele şi o coadă (dimensiunea maximă a cozii reprezintă fereastra) de
pachetele a căror confirmare se aşteaptă Pachetele se icircmpart icircn 4 categorii
1 pachete trimis şi pentru care s-a primit confirmare
2 pachete trimise şi pentru care se aşteaptă icircncă confirmarea
3 pachete care nu au fost trimise icircncă dar care nu depăşesc limitele ferestrei şi deci pot fi
trimise
4 pachete care icircncă nu au fost trimite şi care nici nu vor putea fi trimise decacirct după ce au
fost trimise toate pachetele din categoria 3 şi s-au primit o parte din confirmările la
pachetele din categoria 2
Dacă confirmările pentru pachetele din categoria 2 icircntacircrzie prea mult (un mecanism de timer-e
informează asupra acestui lucru) atunci ele vor fi retrimise Icircn versiunea iniţială TCP-ul nu
permitea decacirct confirmări pozitive ceea ce icircnseamnă că avansarea ferestrei se va icircmpotmoli la
segmentele neconfirmate Cum se poate evita aceasta situaţie vom discuta icircn detaliu icircn capitolele
următoare O soluţie foarte radicală o constituie introducerea de confirmări selective (acest lucru
este realizat de RFC 2018 din octombrie 1996) Această modifică face ca TCP-ul actual să fie un
hibrid de Go-Back-N şi Selective Repeat
Deoarece dimensiunea ferestrei este anunţată la fiecare segment un client lent poate ca pe măsură
ce trimite confirmările să informeze despre progresul icircnregistrat la livrarea datelor următorului
nivel (aplicaţie) Dacă datele vin prea repede pentru viteza cu care clientul procesează datele
fereastra fereastra se va dimiua şi chiar icircnchide (acest lucru se realizează anunţacircnd o fereastră de
dimensiune zero) Cum se realizează efectiv redeschiderea vom analiza icircntr-un capitol viitor
Slow start
Un transfer de date TCP poate să icircnceapă prin transmiterea de segmente pacircnă la umplerea
icircntregii ferestre după care fie se primesc confirmări care vor permite unor noi pachete să fie
trimise fie vor expira timer-ele de retransmisie şi se va icircncepe retrimiterea pachetelor de la
icircnceputul ferestrei Din păcate un astfel de comportament poate duce la pomparea icircn reţea a unui
număr de pachete prea mare pentru capacitatea disponibilă efectiv icircnrăutăţind congestia Pentru
a evita acest lucru s-a propus următoarea soluţie4 iniţial se trimite un segment după primirea
confirmării lui se trimit două segmente după sosirea confirmărilor pentru ele se trimit patru
segmente şi aşa mai departe La un moment dat fie vor icircncepe să se piardă segmente (un indiciu
că s-a atins capacitatea maximă a canalului) fie se va umple fereastra pe care o anunţă cel care
primeşte Trebuie să remarcam că datorită creşterii exponenţiale a numărului de segmente se va
atinge destul de repede una din cele două situaţii
Modalitatea efectivă de implementare a acestui algoritm are la bază utilizarea unei ferestre de
congestie (congestion window cwnd) care este iniţializată cu dimensiunea unui segment (cwnd
se calculează icircn octeţi) şi la fiecare pas este dublată fereastra efectivă din cadrul căreia se pot
trimite segmente este dată de minimul dintre ultima fereastra comunicată de partener şi cwnd
Footnotes
soluţie4
Soluţia aparţine lui V Jacobson şi a fost prezentată icircn 1988 la conferinţă ACM
SIGCOMM-88
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Deoarece TCP trebuie să funcţioneze icircn condiţii variate de latenţă modul icircn care se face
retransmiterea trebuie să fie cacirct mai flexibil (şi simplu icircn acelaşi timp pentru a introduce un
overhead cacirct mai mic) Timpul cacirct se aşteaptă venirea unei confirmări (retransmission timeout
RTO) este calculat prin cronometrarea timpului care icirci ia unui segment trimis să fie confirmat
Pentru o anumită conexiune se cronometrează cacircte un singur segment la un moment dat iar pe
baza RTT-ului măsurat se actualizează valoare RTO-ului
Icircn RFC 793 formula de calcul a RTO-ului este următoarea
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
2 Formatul pachetelor UDP
Datagramele UDP sunt formate dintr-un antet (figura 71) urmat de datele care se doresc
transmise (dacă există)
Figura 71 Structura unei datagrame UDP
Antetul cuprinde
port sursă - 16 biţi
Icircmpreună cu adresa IP a sursei acest număr identifică icircn mod unic locul de unde a fost
trimis datagrama UDP
port destinaţie - 16 biţi
Icircmpreună cu adresa IP a destinaţiei acest număr identifică icircn mod unic destinaţia dorită
pentru datagrama UDP
lungimea pachetului UDP - 16 biţi
Lungimea minimă măsoară datagrama UDP cu tot cu antent şi prin urmare are o valoare
minimă de 8 octeţi
sumă de control - 16 biţi
Suma de control acoperă icircntreg pachetul UDP cacirct şi un pseudo antet de 12 octeţi format
din
adresa IP a sursei - 32 biţi
o adresa IP a destinaţiei - 32 biţi
8 biţi de zero pentru aliniere
numărul protocolului UDP (17) reprezentat pe 8 biţi
lungimea pachetului UDP - 16 biţi
Deoarece suma de control necesită icircn calculul ei un număr multiplu de 16 octeţi la
sfacircrşitul datelor se adaugă un număr potrivit de octeţi de zero Dacă suma este 0 atunci ea
va fi stocată ca 65535 (toţi biţii pe 1) Un 0 icircn cacircmpul de sumei de control indică faptul
că suma de control nu a fost calculată Observaţie chiar dacă un client are inhibat (icircn
mod explicit) calcului sumei de control el este obligat să verifice suma pachetelor care
sosesc şi au suma calculată
2 TCP
Subsections
1 Caracteristici TCP
2 Formatul pachetelor TCP
3 Iniţierea şi terminarea unei conexiuni TCP
o Protocolul de iniţiere
1 Deschiderea simultană
o Protocolul de terminare
2 Terminarea simultană
3 Resetarea conexiunii
o Diagrama de stări
4 Controlul fluxului
o Icircntacircrzierea confirmărilor
o Algoritmul Nagle
o Fereastra glisantă
o Slow start
o Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
o Evitarea congestiei
o Fast Retransmission Fast Recovery
o Sindromul ``Silly Window
o TCP Keepalive Timer
1 Caracteristici TCP
Deoarece protocolul IP este de tip datagramă utilizarea lui direct icircn aplicaţii care in general au
nevoie de conexiuni sigure este mult prea anevoioasă Din aceste motive peste IP a fost construit
un alt protocol TCP (transimission control protocol) care corectează aceste probleme Prima
definire se găseşte icircn RFC-ul cu numărul 793 şi datează din septembrie 1981 Din cauza deselor
congestii apărute icircn 1986 algoritmul care stă la baza TCP-ului este reanalizat şi icircn octombrie
1989 icircn RFC-ul cu numărul 1122 este publicată o nouă specificare mult mai eficientă şi
neambiguă a TCP-ului Noi probleme legate de viteze mari sunt tratate icircn RFC-ul 1323 iar icircn
2018 TCP-ul este extins pentru a permite confirmările selective (selective acknowledge) Seria
de RFC-urie fundamentale este icircncheiată de apariţia icircn 1989 a RFC-ului cu numărul 2581 Icircn el
se specifică foarte strict comportamentul care este permis pentru o implementare de TCP
Alături de protocolul UDP TCP se situează pe nivelul transport icircn ierarhia de protocoale deci
icircntre nivelul aplicaţie şi nivelul reţea Dar cu toate că se bazează pe acelaşi protocol (IP) ca şi
UDP TCP furnizează către nivelul aplicaţie cu totul alt tip de servicii servicii orientate-
conexiune sigure de tip flux de octeţi
Termenul de orientat-conexiune presupune că icircntre cele două aplicaţii care comunică utilizacircnd
TCP trebuie să se stabilească o conexiune TCP icircnainte ca transferul de date să aibă loc Această
conexiune nu este efectiv una fizică ci virtuală asemănător cum se icircntacircmplă icircn sistemul de
telefonie clasică cineva formează un număr şi abia icircn momentul icircn care cealaltă persoană
răspunde se poate icircncepe conversaţia Fiind o conexiune host-la-host nu există noţiunile de
broadcast sau multicast
Transferul sigur de date este asigurat icircn următorul mod
Datele sunt icircmpărţite icircn bucăţi a căror dimensiune optimă e determinată de TCP spre
deosebire de UDP care trimite datagrame UDP corespunzătoare cu dimensiunea datelor
primite de la nivelul aplicaţie Unitatea de date trimisă de TCP către nivelul reţea poartă
numele de segment
Cacircnd TCP trimite un segment porneşte un timer şi dacă nu se primeşte confirmarea
segmentului respectiv icircntr-un anumit timp icircl retransmite
Icircn momentul icircn care se primeşte un segment TCP trimite o confirmare (din motive de
eficienţă aceasta poate fi amacircnată un anumit interval de timp)
Icircn headerul TCP este menţinută o sumă de control pentru detectarea modificărilor icircn date
Dacă se recepţionează un segment corupt TCP icircl ignoră urmacircnd să fie retransmis datorită
neprimirii confirmării
Deoarece segmentele TCP sunt transmise mai departe icircncapsulate icircn datagrame IP iar
acestea pot ajunge icircn orice ordine segmentele TCP pot ajunge icircn altă ordine decacirct cea icircn
care au fost trimise De aceea la destinaţie TCP-ul trebuie să se folosească de numere de
secvenţă pentru a reordona eventual segmentele icircnainte de a le livra către nivelul
aplicaţie De asemenea TCP trebuie să asigure ignorarea duplicatelor
TCP asigură controlul fluxului icircn condiţiile icircn care viteza de trimitere a datelor de la sursă
poate fi mult prea mare decacirct capacitatea de prelucrare de la destinaţie
Serviciul oferit de TCP este de tip flux de octeţi deoarece oferă garanţii că fluxul de date trimis
de sursă va fi livrat fără modificări la destinaţie Comparativ UDP-ul produce pentru fiecare
transfer cerut de nivelul aplicaţie un pachet IP (care ulterior poate fi supus fragmentării) care
dacă ajunge la destinaţie corect va fi livrat direct nivelului aplicaţie fără a garanta icircn vreun fel
ordinea
2 Formatul pachetelor TCP
Pachetele de date transmise de TCP segmentele sunt formate dintr-un antet (figura 72) de 20
octeţi urmat de datele primite de la nivelul aplicaţie Antetul poate uneori conţine şi o serie de
opţiuni caz icircn care poate ajunge la 60 octeţi
Figura 72 Structura unui segment TCP
Antetul unui segment TCP cuprinde
port sursă - 16 biţi pentru specificarea portului aplicaţiei transmiţătoare
port destinaţie - 16 biţi pentru specificarea portului aplicaţiei ce recepţionează segmentul
TCP
Aceste două porturi icircmpreună cu adresele ale sursei şi destinaţiei conţinute icircn antet-ul IP
identifică icircn mod unic conexiunea Pentru o pereche formată dintr-o adresă IP şi un port
se foloseşte adesea denumirea de socket (denumire introdusă icircn specificaţiile iniţiale ale
protocolului TCP icircn RFC 793)
număr de secvenţă - 32 biţi
Pentru a asigura un serviciu de tip flux de octeţi TCP numerotează fiecare octet de date
utilizacircnd un număr de secvenţă Numărul de secvenţă din cadrul antetului TCP specifică
destinaţiei care este primul octet din fluxul trimis La iniţierea unei conexiuni se setează
flag-ul SYN şi se alege aleator un număr de secvenţă de icircnceput utilizacircnd un generator de
numere de secvenţă ISN (Initial sequence number) Numărul de secvenţă al primului
octet de date va fi numărul generat ISN plus 1 deoarece pachetul de iniţiere (cu SYN
setat) consumă şi el un număr de secvenţă Se va vedea mai departe că şi flag-ul de
terminare a conexiunii FIN consumă şi el un număr de secvenţă
confirmare - 32 biţi
Reprezintă numărul de secvenţă al octetului de date pe care transmiţătorul confirmării se
aşteaptă să-l primească Astfel dacă s-a recepţionat octetul cu numărul de secvenţă x (icircn
numerotaţia sursei) pachetul de confirmare va avea flag-ul ACK setat şi va conţine
numărul de confirmare x + 1 Trimiterea unui ACK nu consumă un număr de secvenţă
deoarece atacirct acest cacircmp cacirct şi flag-ul ACK fac parte din antet şi după stabilirea
conexiunii ambele cacircmpuri devin active Acest mecanism nu permite confirmări selective
pentru că numărul de secvenţă specifică pacircnă unde s-au recepţionat date De exemplu
dacă la destinaţie au ajuns octeţii 1-1024 şi următorul segment primit conţine octeţii
2049-3072 nu se poate trimite confirmare pentru cel de-al doilea segment deci
confirmarea va cuprinde numărul de secvenţă 1025
lungimea antetului - 4 biţi
Specifică dimensiunea antetului ca număr de cuvinte de 32 de biţi (4 octeţi) Antetul
poate avea icircntre 20 şi 60 de octeţi deci valoarea acestui cacircmp va fi icircntre 5 (5 x 4 = 20
octeţi) şi 15 (15 x 4 = 60)
6 biţi rezervaţi pentru utilizări viitoare
6 biţi de control reprezentacircnd următoarele flag-uri ce pot fi setate simultan
o URG - cacircmpul urgent pointer este valid
o ACK - cacircmpul de confirmare este valid
o PSH - destinaţia trebuie să trimită datele către nivelul aplicaţie cacirct mai devreme
o RST - se doreşte resetarea conexiunii
o SYN - iniţierea conexiunii
o FIN - icircnchiderea conexiunii
dimensiunea ferestrei - 16 biţi
Reprezintă numărul de octeţi (icircncepacircnd cu numărul de secvenţă conţinut icircn cacircmpul de
confirmare) pe care destinaţia e dispusă să-l primească Este limitat la 65535 octeţi dar
cu toate că pare o limită destul de mare există situaţii cacircnd se doresc valori mult mai
mari Icircn acest scop se folosesc nişte opţiuni speciale descrise ceva mai tacircrziu care permit
scalarea ferestrei
suma de control - 16 biţi
Această sumă de control acoperă icircntregul segment TCP (atacirct datele cacirct şi antetul TCP) şi
spre deosebire de UDP este obligatoriu să fie completat de transmiţător şi verificat de
receptor Dar ca şi icircn cazul UDP-ului la calculul sumei de control se ia in considerare şi
o zona specială de 12 octeţi ce cuprinde pentru re-verificare cacircmpuri din antetul IP
(adresa IP a sursei şi a destinaţiei)[aici tre sa vina o referire la poza cu pseudo-antetu]
După adăugarea acestui pseudo-antet datele se icircmpart icircn cuvinte de 16 biţi icircn vederea
calculării sumei de control adăugacircndu-se eventual şi un octet de aliniere
urgent pointer - 16 biţi
Este utilizat pentru specificarea deplasamentului ultimului octet de date trimis icircn regim
urgent Astfel ultimul octet din secvenţa urgentă se obţine adunacircnd acest cacircmp la
numărul de secvenţă Ce icircnseamnă acest mod urgent de transmitere există situaţii icircn care
aplicaţiile vor să trimită date `neordonate` Să presupunem că aplicaţia a trimis către
nivelul transport o cantitate mare de date dar la un moment dat observă ceva icircn neregulă
şi doreşte să anuleze operaţia Dacă trimite o comandă de anulare aceasta va fi adăugată
la sfacircrşitul şirului de octeţi deci nu se va putea icircmpiedica ajungerea acestora la nivelul
aplicaţie de la receptor Activacircnd modul urgent datele urgente (comanda de anulare) vor
fi plasate la icircnceputul pachetului Aplicaţiile mai cunoscute care folosesc acest mod sunt
Telnet Rlogin şi FTP
opţiuni - pacircnă la 40 de octeţi (figura 73)
Cele mai utilizate opţiuni sunt
o Sfacircrşit de opţiuni (end of option) - 1 octet
Este utilizat pentru alinierea datelor conţinute icircn cacircmpul de opţiuni Nu poate fi
utilizat decacirct o singură dată marcacircndu-se astfel sfacircrşitul opţiunilor şi icircnceperea
datelor efective Dacă pentru alinierea la un cuvacircnt de 32 de biţi e nevoie de mai
mult de 1 byte se va utiliza opţiunea no operation Orice apare după această
opţiune pacircnă la icircnceputul cuvacircntului următor de 32 de biţi e ignorat
o no operation - 1 octet
Utilizat pentru alinierea la cuvinte de 32 de biţi
o Dimensiunea maximă a segmentului (Maximum Segment Size (MSS)) - 16 biţi
Icircn ciuda denumirii defineşte lungimea maximă a datelor nu dimensiunea
icircntregului segment Poate lua valori icircntre 0 şi 65535 valoarea implicită fiind 536
Această opţiune e valabilă doar icircn pachetele de iniţiere a conexiunii (cele cu flag-
ul SYN setat) fiecare parte făcacircnd cunoscută dimensiunea maximă a datelor
dispusă să le primească icircntr-un pachet Icircn principiu cu cacirct această valoarea e mai
mare e mai bine (deoarece se recuperează din spaţiul ocupat de antetele TCP şi
IP) pacircnă cacircnd apare fragmentarea Valoarea maximă la care se poate seta este
MTU (Maximum Transfer Unit) minus dimensiunea antetului IP şi TCP (1460
octeţi icircn cazul Ethernet)
o Factor de scalare a ferestrei (Window scale factor) - 1 octet
Pentru situaţiile icircn care se doreşte utilizarea unei ferestre mai mare de 65535 bytes
se poate utiliza acest cacircmp pentru mărirea dimensiunii ferestrei Noua dimensiune
va fi Chiar dacă
factorul de scalare poate fi maxim 255 icircn cazul TCPIP el nu poate depăşi
valoarea 16 deoarece dimensiunea maximă a ferestrei nu poate fi mai mare decacirct
valoarea celui mai mare număr de secvenţă ( )
Acest factor se poate seta doar la iniţierea conexiunii Icircn timpul transferului de
date se poate modifica dimensiunea ferestrei dar factorul de scalare rămacircne
acelaşi Dacă cel care a iniţiat conexiunea a trimis icircn segmentul de iniţiere şi acest
factor dar icircn pachetul cu ACK destinatarul nu şi-a trimis şi el factorul atunci se la
considera 0 icircn ambele direcţii Invers dacă cel care solicită deschiderea
conexiunii nu setează factorul destinaţia nu va putea seta factorul de scalare
o Timestamp - 10 octeţi
Utilizat pentru reţinerea timpului icircn vederea calculării RTT (Round Trip Time)
Cacircmpul timestamp e completat de sursă icircn momentul trimiterii segmentului La
destinaţie valoarea este reţinută şi copiată icircn cacircmpul timestamp echo reply al
pachetului cu confirmarea RTT-ul este calculat de sursă făcacircnd diferenţa dintre
timpul curent şi această valoare
Figura Opţiuni TCP
3 Iniţierea şi terminarea unei conexiuni TCP
TCP este un protocol orientat conexiune deci presupune stabilirea unei căi virtuale icircntre sursă şi
destinaţie
Subsections
Protocolul de iniţiere
o 1 Deschiderea simultană
Protocolul de terminare
o 2 Terminarea simultană
o 3 Resetarea conexiunii
Diagrama de stări
Protocolul de iniţiere
Modul de transmisie icircn cazul protocolului TCP este full-duplex deci sunt transmise date
simultan icircn ambele direcţii Aceasta presupune că cel care iniţiază conexiunea trebuie să
primească aprobarea celuilalt capăt icircnainte de icircnceperea transferului de date sursa icircşi anunţă
intenţia de a iniţia o conexiune destinaţia trimite un pachet cu confirmarea cererii şi un pachet de
iniţiere a conexiunii de la el la sursă iar apoi sursa confirmă cererea primită de la destinaţie Paşii
2 şi 3 pot fi realizaţi prin trimiterea unui singur pachet de aceea protocolul de iniţiere este
cunoscut sub numele de three-way handshake
Icircn cadrul protocolului de iniţiere există 2 tipuri de cereri de iniţiere cerere activă (active open)
iniţiată de clientul ce doreşte să stabilească conexiunea cu serverul şi cerere pasivă (passive
open) din partea serverului
Cei 3 paşi sunt
1 Clientul trimite un segment cu flag-ul SYN setat şi care conţine portul sursă portul de la
destinaţie şi numărul de secvenţă generat iniţial (ISN) de la care se vor numerota octeţii
de la client către server Opţional se pot stabili parametrii conexiunii prin setarea lungimii
maxime a segmentelor (MSS) dispus să le primească de la server factorului de scalare a
ferestrei Acest prim segment nu conţine nici un parametru de confirmare şi de asemenea
nu are rost să conţine să seteze dimensiunea ferestrei
2 Al doilea segment e trimis de server şi are un rol dublu confirmă segmentul primit de la
client prin setarea flag-ului ACK şi completează numărul de secvenţă cu numărul de
secvenţă primit plus 1 şi al doilea rol iniţializează conexiunea de la el către client prin
setarea flag-ului SYN şi generarea unui număr de secvenţă iniţial ce va fi folosit icircn
numerotarea octeţilor de la server spre client Pe lacircngă aceasta trebuie să conţină
dimensiunea ferestrei şi opţional poate seta factorul de scalare şi dimensiunea maximă a
segmentului acceptat
3 Clientul trimite un segment cu confirmarea cererii din partea serverului (ACK setat +
completează numărul confirmat cu numărul de secvenţa primit + 1) Ca şi icircn cazul
pasului 2 trebuie să seteze dimensiunea ferestrei Acest pachet poate conţine date
Subsections
1 Deschiderea simultană
1 Deschiderea simultană
Se poate icircntacircmpla ca uneori cele două capete care vor să comunice să icircncerce să stabilească
conexiunea simultan Icircn acest caz după ce fiecare a trimis segmentul de iniţiere (iniţiere activă)
ambele vor trimite un segment cu SYN + ACK şi se va stabili o singură conexiune nu două
Protocolul de terminare
Oricare dintre cele două părţi poate solicita icircnchiderea conexiunii dar conexiunea fiind full-
duplex transferul de date icircn celălalt sens poate continua (această situaţie e denumită half-close)
O icircnchidere completă a unei conexiuni TCP presupune următorii paşi
1 Clientul trimite un segment cu flag-ul FIN activat solicitacircnd icircnchiderea conexiunii
2 Serverul trimite un segment ACK confirmacircnd primirea cererea Numărul de confirmare
se completează normal ca numărul de secvenţă primit + 1
3 Serverul continuă să trimită date către client şi cacircnd doreşte să icircnchidă şi el conexiunea
trimite un segment cu FIN activat
4 Clientul trimite un pachet ACK confirmacircnd icircnchiderea conexiunii
Cel care iniţiază primul procedura de icircnchidere (trimite primul FIN) realizează o icircnchidere activă
(active close) iar celălalt capăt o icircnchidere pasivă (passive close) Icircn mod normal cel care
realizează iniţierea activă va fi primul ce va trimite FIN dar oricare dintre cei doi poate icircnchide
activ conexiunea
Subsections
2 Terminarea simultană
3 Resetarea conexiunii
2 Terminarea simultană
Icircn mod similar cu deschiderea simultană există posibilitatea ca ambele capete ale conexiunii TCP
să iniţieze simultan procedura de icircnchidere a conexiunii Icircn acest caz ambele părţi vor trimite
FIN şi vor aştepta primirea unui ACK Icircn continuare fiecare va primi cererea de terminare şi va
trimite ACK Se observă că numărul de segmente transferate pentru realizarea icircnchiderii
conexiunii (4 segmente) este acelaşi ca la terminarea normală
3 Resetarea conexiunii
Există situaţii icircn care TCP doreşte resetarea conexiunii De exemplu dacă se solicită iniţierea
unei conexiuni la un port inexistent Icircn acest caz cealaltă parte va trimite un segment cu bitul
RST setat pentru a anula solicitarea O altă situaţie este atunci cacircnd se constată că celalalt capăt
al conexiunii nu răspunde un anumit timp (timeout)
Diagrama de stări
Toate evenimentele ce au loc icircn timpul stabilirii conexiunii transferului şi icircnchiderii conexiunii
pot fi rezumate printr-un automat finit cunoscut sub numele de diagrama de stări După cum
chiar numele sugerează este o maşină cu un număr limitat de stări O stare este păstrată pacircnă icircn
momentul apariţiei unui eveniment moment icircn care se poate trece icircn altă stare şisau efectua o
acţiune
Aceste stări posibile sunt (denumirile sunt asemănătoare cu cele utilizate de netstat) cele din
tabelul 71
Tabela Stările diagramei de stări TCP
Stare Descriere
CLOSED Nu există conexiune
LISTEN Serverul aşteaptă cereri de la clienţi
SYN_SENT Cerere de iniţiere (activă) a conexiunii Se
aşteaptă confirmarea
SYN_RCVD S-a primit o cerere de iniţiere conexiune
ESTABLISHED S-a stabilit conexiunea
FIN_WAIT_1 Aplicaţia a solicitat icircnchiderea conexiunii
FIN_WAIT_2 Serverul a acceptat icircnchiderea conexiunii
CLOSING Ambele părţi solicită simultan icircnchiderea
conexiunii
TIME_WAIT Conexiune icircnchisă dar se aşteaptă ca
pachetele retransmise să dispară
CLOSE_WAIT Serverul aşteaptă icircnchiderea dinspre partea
aplicaţiei
LAST_ACK Serverul a icircnchis conexiunea Aşteaptă
ultima confirmare
Icircn diagrama ilustrată icircn figura 74 putem observa 3 tipuri de tranziţii icircntre cele 11 stări tranziţii
ce corespund unei funcţionări normale pentru client (linii normale continue) pentru server (linii
normale icircntrerupte) şi tranziţii pentru situaţii nestandard (linii subţiri continue)
O comportarea normală pentru client presupune parcurgerea următoarelor stări CLOSED
SYN_SEND ESTABLISHED FIN_WAY_1 FIN_WAY_2 TIME_WAIT
Iniţial clientul TCP se află icircn starea CLOSED
Aşteptacircnd icircn starea CLOSED clientul poate primi de la aplicaţie o cerere de iniţiere
activă a unei conexiuni Trimite un segment SYN şi trece icircn starea SYN_SENT
Icircn starea SYN_SENT clientul aşteaptă de la server un segment ACK+SYN după care
trimite un ACK şi trece icircn starea ESTABLISHED Din acest moment poate icircncepe
transferul efectiv de date Clientul va rămacircne icircn această stare cacirct timp are de trimisprimit
date
Aflat icircn această stare clientul TCP poate primi din partea aplicaţiei o cerere de icircnchidere a
conexiunii Icircn acest caz va trimit un segment FIN şi trece icircn starea FIN_WAIT_1
Icircn această stare clientul aşteaptă ACK din partea serverului După ce-l primeşte
conexiunea icircntr-un sens se va icircnchide şi clientul trece icircn starea FIN_WAIT_2
Starea FIN_WAIT_2 durează pacircnă cacircnd primeşte cererea de icircnchidere a conexiunii FIN
din partea serverului Trimite ACK şi va trece icircn starea TIME_WAIT
Icircn această stare se va porni un timer cu valoarea setată la dublul timpului de viaţă estimat
pentru un segment de lungime maximă MSL (Maximum Segment Lifetime) Acest timer
permite retransmiterea ACK-ului icircn cazul icircn care acesta se pierde (celălalt capăt va da
timeout şi va retransmite segmentul FIN) Icircn tot acest time cei doi sockeţi (de la client şi
server) nu vor putea fi reutilizaţi Totodată pachetele icircntacircrziate care sosesc icircn această
perioadă sunt ignorate După expirarea acestui timer clientul revine icircn starea iniţială
CLOSED
Din punctul de vedere al unui server o comportare standard parcurge următoarele stări
CLOSED LISTEN SYN_RCVD ESTABLISHED CLOSE_WAIT şi LAST_ACK
Iniţial serverul TCP se află icircn starea CLOSED
Icircn această stare poate primi de la aplicaţia server o cerere de iniţiere activă şi trece icircn
starea LISTEN
Aflat icircn starea LISTEN serverului TCP poate recepţiona un segment SYN de la un client
TCP Icircn acest caz va trimite ACK+SYN şi va trece icircn starea SYN_RCVD
Icircn această stare serverul aşteaptă primirea confirmării de la client moment icircn care
conexiunea e stabilită icircn ambele sensuri şi se poate icircncepe transferul de date (starea
ESTABLISHED)
Clientul TCP poate solicita icircnchiderea conexiunii trimiţacircnd un segment FIN către server
Icircn acest caz serverul TCP trimite confirmarea şi trece icircn starea CLOSE_WAIT
Icircn această stare serverul aşteaptă să primească din partea programului server icircnchiderea
conexiunii moment icircn care va trimite către client un segment FIN şi trece icircn starea
LAST_ACK
Serverul aşteaptă primirea ultimei confirmări de la client după care revine icircn starea
CLOSED
Atacirct serverul cacirct şi clientul TCP se pot afla icircn oricare din cele 11 stări ale diagramei
Figura Diagrama de stări pentru TCP
4 Controlul fluxului
Dacă icircncă de la icircnceput s-a reuşit stabilirea formatului unui pachet TCP şi a modulului icircn care
trebuie să se facă icircnchiderea şi deschiderea unei conexiuni nu acelaşi lucru se poate spune şi
despre modul icircn care ar trebui să se realizeze controlul fluxului Ţinacircnd seama icircnsă că din 1989
(de cacircnd datează RFC-ul 2581 cel despre care am menţionat că specifică icircn mod clar modul icircn
care trebuie să se comporte o implementare de TCP) TCP-ul a rămas neschimbat putem să icircl
considerăm un rezultat important al domeniului reţelor de calculatoare
Icircn cele ce urmează vom icircnţelege prin controlul fluxului totalitatea algoritmilor care permit
atingerea unei viteze de transfer punct-la-punct cacirct mai mare pentru toate conexiunile existente
Icircn principal aceşti algoritmi stabilesc modul icircn care segmentele şi confirmările trebuie trimise şi
ce acţiuni trebuie executate icircn situaţiile icircn care răspunsurile aşteptate de la celălalt capăt icircntacircrzie
să vină
Subsections
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
Icircntacircrzierea confirmărilor
O modalitate simplă de generare a confirmărilor este de a trimite cacircte una pentru fiecare segment
primit Această politică prezintă avantajul de a face comunicaţia self-clocking icircnsă este
ineficientă dacă segmentele care nu conţin decacirct confirmări sunt urmate la scurtă distanţă (cacircteva
zeci de milisecunde) de segmente ce conţin date efective Pentru a evita această situaţie se
procedează2 la icircntacircrzierea (200ms este o valoare uzuală icircn RFC 1122 se specifică o valoare
maximă de 500ms) a segmentelor care conţin doar confirmări Această strategie face posibil ca
un răspuns generat de primirea unor date să plece sper celălalt capăt icircn acelaşi segment cu
confirmarea
Observaţie deoarece este dificil de menţinut timere pentru fiecare confirmare diferenţa de
200ms este calculată de un timer global Din acest motiv modul efectiv de comportare poate fi
descris şi icircn felul următor cacircnd un segment nu conţine decacirct o confirmare el este pus icircntr-o
coadă ce va fi inspectată de un proces care din 200 icircn 200 ms trimite tot ce s-a acumulat icircn
coada
Footnotes
2
Acest comportament a fost propus de David D Clark icircn iulie 1982 icircn RFC 813
Algoritmul Nagle
Acest algoritm3 icircncearcă să icircmbunătăţească performanţele exploatacircnd următoarea caracteristică
foarte des icircntacirclnită icircn dialogul dintre două staţii dacă se icircncearcă trimiterea unor date de
dimensiune mică icircnsă există icircncă date neconfirmate de partener atunci ele sunt buffer-ate şi
trimise icircntr-un segment mai mare cacircnd soseşte confirmarea aşteptată Icircn acest fel se poate evita
generarea datagramelor mici (tinygrame) icircn situaţia unei legături lente Icircn cazul unei legături
rapide confirmările vor veni repede şi icircntacircrzierea introdusă de algoritm va neglijabilă
Există icircnsă şi cazuri icircn care acest algoritm duce la deprecierea performanţelor mesajele scurte
generate de mişcările mouse-ului icircn cazul folosirii unui server X Window sau utilizarea tastelor
care trimit mai mult de un caracter (secvenţe escape) Pentru a rezolva aceste inconveninte API-
ul de utilizare a TCP-ului trebuie să ofere o modalitate de a dezactiva acest algoritm (icircn sistemele
bazate pe sockeţi există icircn acest scop opţiunea TCP_NODELAY)
Footnotes
algoritm3
Algoritmul aparţinacircnd lui John Nagle a fost propus icircn ianuarie 1984 icircn RFC 896
Fereastra glisantă
Algoritmul implementat de TCP pentru a implementa transferul sigur de date este cunoscut icircn
teorie sub numele de Go-Back-N Icircn acest algoritm se utilizează numere de secvenţă pentru a
distinge pachetele icircntre ele şi o coadă (dimensiunea maximă a cozii reprezintă fereastra) de
pachetele a căror confirmare se aşteaptă Pachetele se icircmpart icircn 4 categorii
1 pachete trimis şi pentru care s-a primit confirmare
2 pachete trimise şi pentru care se aşteaptă icircncă confirmarea
3 pachete care nu au fost trimise icircncă dar care nu depăşesc limitele ferestrei şi deci pot fi
trimise
4 pachete care icircncă nu au fost trimite şi care nici nu vor putea fi trimise decacirct după ce au
fost trimise toate pachetele din categoria 3 şi s-au primit o parte din confirmările la
pachetele din categoria 2
Dacă confirmările pentru pachetele din categoria 2 icircntacircrzie prea mult (un mecanism de timer-e
informează asupra acestui lucru) atunci ele vor fi retrimise Icircn versiunea iniţială TCP-ul nu
permitea decacirct confirmări pozitive ceea ce icircnseamnă că avansarea ferestrei se va icircmpotmoli la
segmentele neconfirmate Cum se poate evita aceasta situaţie vom discuta icircn detaliu icircn capitolele
următoare O soluţie foarte radicală o constituie introducerea de confirmări selective (acest lucru
este realizat de RFC 2018 din octombrie 1996) Această modifică face ca TCP-ul actual să fie un
hibrid de Go-Back-N şi Selective Repeat
Deoarece dimensiunea ferestrei este anunţată la fiecare segment un client lent poate ca pe măsură
ce trimite confirmările să informeze despre progresul icircnregistrat la livrarea datelor următorului
nivel (aplicaţie) Dacă datele vin prea repede pentru viteza cu care clientul procesează datele
fereastra fereastra se va dimiua şi chiar icircnchide (acest lucru se realizează anunţacircnd o fereastră de
dimensiune zero) Cum se realizează efectiv redeschiderea vom analiza icircntr-un capitol viitor
Slow start
Un transfer de date TCP poate să icircnceapă prin transmiterea de segmente pacircnă la umplerea
icircntregii ferestre după care fie se primesc confirmări care vor permite unor noi pachete să fie
trimise fie vor expira timer-ele de retransmisie şi se va icircncepe retrimiterea pachetelor de la
icircnceputul ferestrei Din păcate un astfel de comportament poate duce la pomparea icircn reţea a unui
număr de pachete prea mare pentru capacitatea disponibilă efectiv icircnrăutăţind congestia Pentru
a evita acest lucru s-a propus următoarea soluţie4 iniţial se trimite un segment după primirea
confirmării lui se trimit două segmente după sosirea confirmărilor pentru ele se trimit patru
segmente şi aşa mai departe La un moment dat fie vor icircncepe să se piardă segmente (un indiciu
că s-a atins capacitatea maximă a canalului) fie se va umple fereastra pe care o anunţă cel care
primeşte Trebuie să remarcam că datorită creşterii exponenţiale a numărului de segmente se va
atinge destul de repede una din cele două situaţii
Modalitatea efectivă de implementare a acestui algoritm are la bază utilizarea unei ferestre de
congestie (congestion window cwnd) care este iniţializată cu dimensiunea unui segment (cwnd
se calculează icircn octeţi) şi la fiecare pas este dublată fereastra efectivă din cadrul căreia se pot
trimite segmente este dată de minimul dintre ultima fereastra comunicată de partener şi cwnd
Footnotes
soluţie4
Soluţia aparţine lui V Jacobson şi a fost prezentată icircn 1988 la conferinţă ACM
SIGCOMM-88
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Deoarece TCP trebuie să funcţioneze icircn condiţii variate de latenţă modul icircn care se face
retransmiterea trebuie să fie cacirct mai flexibil (şi simplu icircn acelaşi timp pentru a introduce un
overhead cacirct mai mic) Timpul cacirct se aşteaptă venirea unei confirmări (retransmission timeout
RTO) este calculat prin cronometrarea timpului care icirci ia unui segment trimis să fie confirmat
Pentru o anumită conexiune se cronometrează cacircte un singur segment la un moment dat iar pe
baza RTT-ului măsurat se actualizează valoare RTO-ului
Icircn RFC 793 formula de calcul a RTO-ului este următoarea
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
2 TCP
Subsections
1 Caracteristici TCP
2 Formatul pachetelor TCP
3 Iniţierea şi terminarea unei conexiuni TCP
o Protocolul de iniţiere
1 Deschiderea simultană
o Protocolul de terminare
2 Terminarea simultană
3 Resetarea conexiunii
o Diagrama de stări
4 Controlul fluxului
o Icircntacircrzierea confirmărilor
o Algoritmul Nagle
o Fereastra glisantă
o Slow start
o Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
o Evitarea congestiei
o Fast Retransmission Fast Recovery
o Sindromul ``Silly Window
o TCP Keepalive Timer
1 Caracteristici TCP
Deoarece protocolul IP este de tip datagramă utilizarea lui direct icircn aplicaţii care in general au
nevoie de conexiuni sigure este mult prea anevoioasă Din aceste motive peste IP a fost construit
un alt protocol TCP (transimission control protocol) care corectează aceste probleme Prima
definire se găseşte icircn RFC-ul cu numărul 793 şi datează din septembrie 1981 Din cauza deselor
congestii apărute icircn 1986 algoritmul care stă la baza TCP-ului este reanalizat şi icircn octombrie
1989 icircn RFC-ul cu numărul 1122 este publicată o nouă specificare mult mai eficientă şi
neambiguă a TCP-ului Noi probleme legate de viteze mari sunt tratate icircn RFC-ul 1323 iar icircn
2018 TCP-ul este extins pentru a permite confirmările selective (selective acknowledge) Seria
de RFC-urie fundamentale este icircncheiată de apariţia icircn 1989 a RFC-ului cu numărul 2581 Icircn el
se specifică foarte strict comportamentul care este permis pentru o implementare de TCP
Alături de protocolul UDP TCP se situează pe nivelul transport icircn ierarhia de protocoale deci
icircntre nivelul aplicaţie şi nivelul reţea Dar cu toate că se bazează pe acelaşi protocol (IP) ca şi
UDP TCP furnizează către nivelul aplicaţie cu totul alt tip de servicii servicii orientate-
conexiune sigure de tip flux de octeţi
Termenul de orientat-conexiune presupune că icircntre cele două aplicaţii care comunică utilizacircnd
TCP trebuie să se stabilească o conexiune TCP icircnainte ca transferul de date să aibă loc Această
conexiune nu este efectiv una fizică ci virtuală asemănător cum se icircntacircmplă icircn sistemul de
telefonie clasică cineva formează un număr şi abia icircn momentul icircn care cealaltă persoană
răspunde se poate icircncepe conversaţia Fiind o conexiune host-la-host nu există noţiunile de
broadcast sau multicast
Transferul sigur de date este asigurat icircn următorul mod
Datele sunt icircmpărţite icircn bucăţi a căror dimensiune optimă e determinată de TCP spre
deosebire de UDP care trimite datagrame UDP corespunzătoare cu dimensiunea datelor
primite de la nivelul aplicaţie Unitatea de date trimisă de TCP către nivelul reţea poartă
numele de segment
Cacircnd TCP trimite un segment porneşte un timer şi dacă nu se primeşte confirmarea
segmentului respectiv icircntr-un anumit timp icircl retransmite
Icircn momentul icircn care se primeşte un segment TCP trimite o confirmare (din motive de
eficienţă aceasta poate fi amacircnată un anumit interval de timp)
Icircn headerul TCP este menţinută o sumă de control pentru detectarea modificărilor icircn date
Dacă se recepţionează un segment corupt TCP icircl ignoră urmacircnd să fie retransmis datorită
neprimirii confirmării
Deoarece segmentele TCP sunt transmise mai departe icircncapsulate icircn datagrame IP iar
acestea pot ajunge icircn orice ordine segmentele TCP pot ajunge icircn altă ordine decacirct cea icircn
care au fost trimise De aceea la destinaţie TCP-ul trebuie să se folosească de numere de
secvenţă pentru a reordona eventual segmentele icircnainte de a le livra către nivelul
aplicaţie De asemenea TCP trebuie să asigure ignorarea duplicatelor
TCP asigură controlul fluxului icircn condiţiile icircn care viteza de trimitere a datelor de la sursă
poate fi mult prea mare decacirct capacitatea de prelucrare de la destinaţie
Serviciul oferit de TCP este de tip flux de octeţi deoarece oferă garanţii că fluxul de date trimis
de sursă va fi livrat fără modificări la destinaţie Comparativ UDP-ul produce pentru fiecare
transfer cerut de nivelul aplicaţie un pachet IP (care ulterior poate fi supus fragmentării) care
dacă ajunge la destinaţie corect va fi livrat direct nivelului aplicaţie fără a garanta icircn vreun fel
ordinea
2 Formatul pachetelor TCP
Pachetele de date transmise de TCP segmentele sunt formate dintr-un antet (figura 72) de 20
octeţi urmat de datele primite de la nivelul aplicaţie Antetul poate uneori conţine şi o serie de
opţiuni caz icircn care poate ajunge la 60 octeţi
Figura 72 Structura unui segment TCP
Antetul unui segment TCP cuprinde
port sursă - 16 biţi pentru specificarea portului aplicaţiei transmiţătoare
port destinaţie - 16 biţi pentru specificarea portului aplicaţiei ce recepţionează segmentul
TCP
Aceste două porturi icircmpreună cu adresele ale sursei şi destinaţiei conţinute icircn antet-ul IP
identifică icircn mod unic conexiunea Pentru o pereche formată dintr-o adresă IP şi un port
se foloseşte adesea denumirea de socket (denumire introdusă icircn specificaţiile iniţiale ale
protocolului TCP icircn RFC 793)
număr de secvenţă - 32 biţi
Pentru a asigura un serviciu de tip flux de octeţi TCP numerotează fiecare octet de date
utilizacircnd un număr de secvenţă Numărul de secvenţă din cadrul antetului TCP specifică
destinaţiei care este primul octet din fluxul trimis La iniţierea unei conexiuni se setează
flag-ul SYN şi se alege aleator un număr de secvenţă de icircnceput utilizacircnd un generator de
numere de secvenţă ISN (Initial sequence number) Numărul de secvenţă al primului
octet de date va fi numărul generat ISN plus 1 deoarece pachetul de iniţiere (cu SYN
setat) consumă şi el un număr de secvenţă Se va vedea mai departe că şi flag-ul de
terminare a conexiunii FIN consumă şi el un număr de secvenţă
confirmare - 32 biţi
Reprezintă numărul de secvenţă al octetului de date pe care transmiţătorul confirmării se
aşteaptă să-l primească Astfel dacă s-a recepţionat octetul cu numărul de secvenţă x (icircn
numerotaţia sursei) pachetul de confirmare va avea flag-ul ACK setat şi va conţine
numărul de confirmare x + 1 Trimiterea unui ACK nu consumă un număr de secvenţă
deoarece atacirct acest cacircmp cacirct şi flag-ul ACK fac parte din antet şi după stabilirea
conexiunii ambele cacircmpuri devin active Acest mecanism nu permite confirmări selective
pentru că numărul de secvenţă specifică pacircnă unde s-au recepţionat date De exemplu
dacă la destinaţie au ajuns octeţii 1-1024 şi următorul segment primit conţine octeţii
2049-3072 nu se poate trimite confirmare pentru cel de-al doilea segment deci
confirmarea va cuprinde numărul de secvenţă 1025
lungimea antetului - 4 biţi
Specifică dimensiunea antetului ca număr de cuvinte de 32 de biţi (4 octeţi) Antetul
poate avea icircntre 20 şi 60 de octeţi deci valoarea acestui cacircmp va fi icircntre 5 (5 x 4 = 20
octeţi) şi 15 (15 x 4 = 60)
6 biţi rezervaţi pentru utilizări viitoare
6 biţi de control reprezentacircnd următoarele flag-uri ce pot fi setate simultan
o URG - cacircmpul urgent pointer este valid
o ACK - cacircmpul de confirmare este valid
o PSH - destinaţia trebuie să trimită datele către nivelul aplicaţie cacirct mai devreme
o RST - se doreşte resetarea conexiunii
o SYN - iniţierea conexiunii
o FIN - icircnchiderea conexiunii
dimensiunea ferestrei - 16 biţi
Reprezintă numărul de octeţi (icircncepacircnd cu numărul de secvenţă conţinut icircn cacircmpul de
confirmare) pe care destinaţia e dispusă să-l primească Este limitat la 65535 octeţi dar
cu toate că pare o limită destul de mare există situaţii cacircnd se doresc valori mult mai
mari Icircn acest scop se folosesc nişte opţiuni speciale descrise ceva mai tacircrziu care permit
scalarea ferestrei
suma de control - 16 biţi
Această sumă de control acoperă icircntregul segment TCP (atacirct datele cacirct şi antetul TCP) şi
spre deosebire de UDP este obligatoriu să fie completat de transmiţător şi verificat de
receptor Dar ca şi icircn cazul UDP-ului la calculul sumei de control se ia in considerare şi
o zona specială de 12 octeţi ce cuprinde pentru re-verificare cacircmpuri din antetul IP
(adresa IP a sursei şi a destinaţiei)[aici tre sa vina o referire la poza cu pseudo-antetu]
După adăugarea acestui pseudo-antet datele se icircmpart icircn cuvinte de 16 biţi icircn vederea
calculării sumei de control adăugacircndu-se eventual şi un octet de aliniere
urgent pointer - 16 biţi
Este utilizat pentru specificarea deplasamentului ultimului octet de date trimis icircn regim
urgent Astfel ultimul octet din secvenţa urgentă se obţine adunacircnd acest cacircmp la
numărul de secvenţă Ce icircnseamnă acest mod urgent de transmitere există situaţii icircn care
aplicaţiile vor să trimită date `neordonate` Să presupunem că aplicaţia a trimis către
nivelul transport o cantitate mare de date dar la un moment dat observă ceva icircn neregulă
şi doreşte să anuleze operaţia Dacă trimite o comandă de anulare aceasta va fi adăugată
la sfacircrşitul şirului de octeţi deci nu se va putea icircmpiedica ajungerea acestora la nivelul
aplicaţie de la receptor Activacircnd modul urgent datele urgente (comanda de anulare) vor
fi plasate la icircnceputul pachetului Aplicaţiile mai cunoscute care folosesc acest mod sunt
Telnet Rlogin şi FTP
opţiuni - pacircnă la 40 de octeţi (figura 73)
Cele mai utilizate opţiuni sunt
o Sfacircrşit de opţiuni (end of option) - 1 octet
Este utilizat pentru alinierea datelor conţinute icircn cacircmpul de opţiuni Nu poate fi
utilizat decacirct o singură dată marcacircndu-se astfel sfacircrşitul opţiunilor şi icircnceperea
datelor efective Dacă pentru alinierea la un cuvacircnt de 32 de biţi e nevoie de mai
mult de 1 byte se va utiliza opţiunea no operation Orice apare după această
opţiune pacircnă la icircnceputul cuvacircntului următor de 32 de biţi e ignorat
o no operation - 1 octet
Utilizat pentru alinierea la cuvinte de 32 de biţi
o Dimensiunea maximă a segmentului (Maximum Segment Size (MSS)) - 16 biţi
Icircn ciuda denumirii defineşte lungimea maximă a datelor nu dimensiunea
icircntregului segment Poate lua valori icircntre 0 şi 65535 valoarea implicită fiind 536
Această opţiune e valabilă doar icircn pachetele de iniţiere a conexiunii (cele cu flag-
ul SYN setat) fiecare parte făcacircnd cunoscută dimensiunea maximă a datelor
dispusă să le primească icircntr-un pachet Icircn principiu cu cacirct această valoarea e mai
mare e mai bine (deoarece se recuperează din spaţiul ocupat de antetele TCP şi
IP) pacircnă cacircnd apare fragmentarea Valoarea maximă la care se poate seta este
MTU (Maximum Transfer Unit) minus dimensiunea antetului IP şi TCP (1460
octeţi icircn cazul Ethernet)
o Factor de scalare a ferestrei (Window scale factor) - 1 octet
Pentru situaţiile icircn care se doreşte utilizarea unei ferestre mai mare de 65535 bytes
se poate utiliza acest cacircmp pentru mărirea dimensiunii ferestrei Noua dimensiune
va fi Chiar dacă
factorul de scalare poate fi maxim 255 icircn cazul TCPIP el nu poate depăşi
valoarea 16 deoarece dimensiunea maximă a ferestrei nu poate fi mai mare decacirct
valoarea celui mai mare număr de secvenţă ( )
Acest factor se poate seta doar la iniţierea conexiunii Icircn timpul transferului de
date se poate modifica dimensiunea ferestrei dar factorul de scalare rămacircne
acelaşi Dacă cel care a iniţiat conexiunea a trimis icircn segmentul de iniţiere şi acest
factor dar icircn pachetul cu ACK destinatarul nu şi-a trimis şi el factorul atunci se la
considera 0 icircn ambele direcţii Invers dacă cel care solicită deschiderea
conexiunii nu setează factorul destinaţia nu va putea seta factorul de scalare
o Timestamp - 10 octeţi
Utilizat pentru reţinerea timpului icircn vederea calculării RTT (Round Trip Time)
Cacircmpul timestamp e completat de sursă icircn momentul trimiterii segmentului La
destinaţie valoarea este reţinută şi copiată icircn cacircmpul timestamp echo reply al
pachetului cu confirmarea RTT-ul este calculat de sursă făcacircnd diferenţa dintre
timpul curent şi această valoare
Figura Opţiuni TCP
3 Iniţierea şi terminarea unei conexiuni TCP
TCP este un protocol orientat conexiune deci presupune stabilirea unei căi virtuale icircntre sursă şi
destinaţie
Subsections
Protocolul de iniţiere
o 1 Deschiderea simultană
Protocolul de terminare
o 2 Terminarea simultană
o 3 Resetarea conexiunii
Diagrama de stări
Protocolul de iniţiere
Modul de transmisie icircn cazul protocolului TCP este full-duplex deci sunt transmise date
simultan icircn ambele direcţii Aceasta presupune că cel care iniţiază conexiunea trebuie să
primească aprobarea celuilalt capăt icircnainte de icircnceperea transferului de date sursa icircşi anunţă
intenţia de a iniţia o conexiune destinaţia trimite un pachet cu confirmarea cererii şi un pachet de
iniţiere a conexiunii de la el la sursă iar apoi sursa confirmă cererea primită de la destinaţie Paşii
2 şi 3 pot fi realizaţi prin trimiterea unui singur pachet de aceea protocolul de iniţiere este
cunoscut sub numele de three-way handshake
Icircn cadrul protocolului de iniţiere există 2 tipuri de cereri de iniţiere cerere activă (active open)
iniţiată de clientul ce doreşte să stabilească conexiunea cu serverul şi cerere pasivă (passive
open) din partea serverului
Cei 3 paşi sunt
1 Clientul trimite un segment cu flag-ul SYN setat şi care conţine portul sursă portul de la
destinaţie şi numărul de secvenţă generat iniţial (ISN) de la care se vor numerota octeţii
de la client către server Opţional se pot stabili parametrii conexiunii prin setarea lungimii
maxime a segmentelor (MSS) dispus să le primească de la server factorului de scalare a
ferestrei Acest prim segment nu conţine nici un parametru de confirmare şi de asemenea
nu are rost să conţine să seteze dimensiunea ferestrei
2 Al doilea segment e trimis de server şi are un rol dublu confirmă segmentul primit de la
client prin setarea flag-ului ACK şi completează numărul de secvenţă cu numărul de
secvenţă primit plus 1 şi al doilea rol iniţializează conexiunea de la el către client prin
setarea flag-ului SYN şi generarea unui număr de secvenţă iniţial ce va fi folosit icircn
numerotarea octeţilor de la server spre client Pe lacircngă aceasta trebuie să conţină
dimensiunea ferestrei şi opţional poate seta factorul de scalare şi dimensiunea maximă a
segmentului acceptat
3 Clientul trimite un segment cu confirmarea cererii din partea serverului (ACK setat +
completează numărul confirmat cu numărul de secvenţa primit + 1) Ca şi icircn cazul
pasului 2 trebuie să seteze dimensiunea ferestrei Acest pachet poate conţine date
Subsections
1 Deschiderea simultană
1 Deschiderea simultană
Se poate icircntacircmpla ca uneori cele două capete care vor să comunice să icircncerce să stabilească
conexiunea simultan Icircn acest caz după ce fiecare a trimis segmentul de iniţiere (iniţiere activă)
ambele vor trimite un segment cu SYN + ACK şi se va stabili o singură conexiune nu două
Protocolul de terminare
Oricare dintre cele două părţi poate solicita icircnchiderea conexiunii dar conexiunea fiind full-
duplex transferul de date icircn celălalt sens poate continua (această situaţie e denumită half-close)
O icircnchidere completă a unei conexiuni TCP presupune următorii paşi
1 Clientul trimite un segment cu flag-ul FIN activat solicitacircnd icircnchiderea conexiunii
2 Serverul trimite un segment ACK confirmacircnd primirea cererea Numărul de confirmare
se completează normal ca numărul de secvenţă primit + 1
3 Serverul continuă să trimită date către client şi cacircnd doreşte să icircnchidă şi el conexiunea
trimite un segment cu FIN activat
4 Clientul trimite un pachet ACK confirmacircnd icircnchiderea conexiunii
Cel care iniţiază primul procedura de icircnchidere (trimite primul FIN) realizează o icircnchidere activă
(active close) iar celălalt capăt o icircnchidere pasivă (passive close) Icircn mod normal cel care
realizează iniţierea activă va fi primul ce va trimite FIN dar oricare dintre cei doi poate icircnchide
activ conexiunea
Subsections
2 Terminarea simultană
3 Resetarea conexiunii
2 Terminarea simultană
Icircn mod similar cu deschiderea simultană există posibilitatea ca ambele capete ale conexiunii TCP
să iniţieze simultan procedura de icircnchidere a conexiunii Icircn acest caz ambele părţi vor trimite
FIN şi vor aştepta primirea unui ACK Icircn continuare fiecare va primi cererea de terminare şi va
trimite ACK Se observă că numărul de segmente transferate pentru realizarea icircnchiderii
conexiunii (4 segmente) este acelaşi ca la terminarea normală
3 Resetarea conexiunii
Există situaţii icircn care TCP doreşte resetarea conexiunii De exemplu dacă se solicită iniţierea
unei conexiuni la un port inexistent Icircn acest caz cealaltă parte va trimite un segment cu bitul
RST setat pentru a anula solicitarea O altă situaţie este atunci cacircnd se constată că celalalt capăt
al conexiunii nu răspunde un anumit timp (timeout)
Diagrama de stări
Toate evenimentele ce au loc icircn timpul stabilirii conexiunii transferului şi icircnchiderii conexiunii
pot fi rezumate printr-un automat finit cunoscut sub numele de diagrama de stări După cum
chiar numele sugerează este o maşină cu un număr limitat de stări O stare este păstrată pacircnă icircn
momentul apariţiei unui eveniment moment icircn care se poate trece icircn altă stare şisau efectua o
acţiune
Aceste stări posibile sunt (denumirile sunt asemănătoare cu cele utilizate de netstat) cele din
tabelul 71
Tabela Stările diagramei de stări TCP
Stare Descriere
CLOSED Nu există conexiune
LISTEN Serverul aşteaptă cereri de la clienţi
SYN_SENT Cerere de iniţiere (activă) a conexiunii Se
aşteaptă confirmarea
SYN_RCVD S-a primit o cerere de iniţiere conexiune
ESTABLISHED S-a stabilit conexiunea
FIN_WAIT_1 Aplicaţia a solicitat icircnchiderea conexiunii
FIN_WAIT_2 Serverul a acceptat icircnchiderea conexiunii
CLOSING Ambele părţi solicită simultan icircnchiderea
conexiunii
TIME_WAIT Conexiune icircnchisă dar se aşteaptă ca
pachetele retransmise să dispară
CLOSE_WAIT Serverul aşteaptă icircnchiderea dinspre partea
aplicaţiei
LAST_ACK Serverul a icircnchis conexiunea Aşteaptă
ultima confirmare
Icircn diagrama ilustrată icircn figura 74 putem observa 3 tipuri de tranziţii icircntre cele 11 stări tranziţii
ce corespund unei funcţionări normale pentru client (linii normale continue) pentru server (linii
normale icircntrerupte) şi tranziţii pentru situaţii nestandard (linii subţiri continue)
O comportarea normală pentru client presupune parcurgerea următoarelor stări CLOSED
SYN_SEND ESTABLISHED FIN_WAY_1 FIN_WAY_2 TIME_WAIT
Iniţial clientul TCP se află icircn starea CLOSED
Aşteptacircnd icircn starea CLOSED clientul poate primi de la aplicaţie o cerere de iniţiere
activă a unei conexiuni Trimite un segment SYN şi trece icircn starea SYN_SENT
Icircn starea SYN_SENT clientul aşteaptă de la server un segment ACK+SYN după care
trimite un ACK şi trece icircn starea ESTABLISHED Din acest moment poate icircncepe
transferul efectiv de date Clientul va rămacircne icircn această stare cacirct timp are de trimisprimit
date
Aflat icircn această stare clientul TCP poate primi din partea aplicaţiei o cerere de icircnchidere a
conexiunii Icircn acest caz va trimit un segment FIN şi trece icircn starea FIN_WAIT_1
Icircn această stare clientul aşteaptă ACK din partea serverului După ce-l primeşte
conexiunea icircntr-un sens se va icircnchide şi clientul trece icircn starea FIN_WAIT_2
Starea FIN_WAIT_2 durează pacircnă cacircnd primeşte cererea de icircnchidere a conexiunii FIN
din partea serverului Trimite ACK şi va trece icircn starea TIME_WAIT
Icircn această stare se va porni un timer cu valoarea setată la dublul timpului de viaţă estimat
pentru un segment de lungime maximă MSL (Maximum Segment Lifetime) Acest timer
permite retransmiterea ACK-ului icircn cazul icircn care acesta se pierde (celălalt capăt va da
timeout şi va retransmite segmentul FIN) Icircn tot acest time cei doi sockeţi (de la client şi
server) nu vor putea fi reutilizaţi Totodată pachetele icircntacircrziate care sosesc icircn această
perioadă sunt ignorate După expirarea acestui timer clientul revine icircn starea iniţială
CLOSED
Din punctul de vedere al unui server o comportare standard parcurge următoarele stări
CLOSED LISTEN SYN_RCVD ESTABLISHED CLOSE_WAIT şi LAST_ACK
Iniţial serverul TCP se află icircn starea CLOSED
Icircn această stare poate primi de la aplicaţia server o cerere de iniţiere activă şi trece icircn
starea LISTEN
Aflat icircn starea LISTEN serverului TCP poate recepţiona un segment SYN de la un client
TCP Icircn acest caz va trimite ACK+SYN şi va trece icircn starea SYN_RCVD
Icircn această stare serverul aşteaptă primirea confirmării de la client moment icircn care
conexiunea e stabilită icircn ambele sensuri şi se poate icircncepe transferul de date (starea
ESTABLISHED)
Clientul TCP poate solicita icircnchiderea conexiunii trimiţacircnd un segment FIN către server
Icircn acest caz serverul TCP trimite confirmarea şi trece icircn starea CLOSE_WAIT
Icircn această stare serverul aşteaptă să primească din partea programului server icircnchiderea
conexiunii moment icircn care va trimite către client un segment FIN şi trece icircn starea
LAST_ACK
Serverul aşteaptă primirea ultimei confirmări de la client după care revine icircn starea
CLOSED
Atacirct serverul cacirct şi clientul TCP se pot afla icircn oricare din cele 11 stări ale diagramei
Figura Diagrama de stări pentru TCP
4 Controlul fluxului
Dacă icircncă de la icircnceput s-a reuşit stabilirea formatului unui pachet TCP şi a modulului icircn care
trebuie să se facă icircnchiderea şi deschiderea unei conexiuni nu acelaşi lucru se poate spune şi
despre modul icircn care ar trebui să se realizeze controlul fluxului Ţinacircnd seama icircnsă că din 1989
(de cacircnd datează RFC-ul 2581 cel despre care am menţionat că specifică icircn mod clar modul icircn
care trebuie să se comporte o implementare de TCP) TCP-ul a rămas neschimbat putem să icircl
considerăm un rezultat important al domeniului reţelor de calculatoare
Icircn cele ce urmează vom icircnţelege prin controlul fluxului totalitatea algoritmilor care permit
atingerea unei viteze de transfer punct-la-punct cacirct mai mare pentru toate conexiunile existente
Icircn principal aceşti algoritmi stabilesc modul icircn care segmentele şi confirmările trebuie trimise şi
ce acţiuni trebuie executate icircn situaţiile icircn care răspunsurile aşteptate de la celălalt capăt icircntacircrzie
să vină
Subsections
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
Icircntacircrzierea confirmărilor
O modalitate simplă de generare a confirmărilor este de a trimite cacircte una pentru fiecare segment
primit Această politică prezintă avantajul de a face comunicaţia self-clocking icircnsă este
ineficientă dacă segmentele care nu conţin decacirct confirmări sunt urmate la scurtă distanţă (cacircteva
zeci de milisecunde) de segmente ce conţin date efective Pentru a evita această situaţie se
procedează2 la icircntacircrzierea (200ms este o valoare uzuală icircn RFC 1122 se specifică o valoare
maximă de 500ms) a segmentelor care conţin doar confirmări Această strategie face posibil ca
un răspuns generat de primirea unor date să plece sper celălalt capăt icircn acelaşi segment cu
confirmarea
Observaţie deoarece este dificil de menţinut timere pentru fiecare confirmare diferenţa de
200ms este calculată de un timer global Din acest motiv modul efectiv de comportare poate fi
descris şi icircn felul următor cacircnd un segment nu conţine decacirct o confirmare el este pus icircntr-o
coadă ce va fi inspectată de un proces care din 200 icircn 200 ms trimite tot ce s-a acumulat icircn
coada
Footnotes
2
Acest comportament a fost propus de David D Clark icircn iulie 1982 icircn RFC 813
Algoritmul Nagle
Acest algoritm3 icircncearcă să icircmbunătăţească performanţele exploatacircnd următoarea caracteristică
foarte des icircntacirclnită icircn dialogul dintre două staţii dacă se icircncearcă trimiterea unor date de
dimensiune mică icircnsă există icircncă date neconfirmate de partener atunci ele sunt buffer-ate şi
trimise icircntr-un segment mai mare cacircnd soseşte confirmarea aşteptată Icircn acest fel se poate evita
generarea datagramelor mici (tinygrame) icircn situaţia unei legături lente Icircn cazul unei legături
rapide confirmările vor veni repede şi icircntacircrzierea introdusă de algoritm va neglijabilă
Există icircnsă şi cazuri icircn care acest algoritm duce la deprecierea performanţelor mesajele scurte
generate de mişcările mouse-ului icircn cazul folosirii unui server X Window sau utilizarea tastelor
care trimit mai mult de un caracter (secvenţe escape) Pentru a rezolva aceste inconveninte API-
ul de utilizare a TCP-ului trebuie să ofere o modalitate de a dezactiva acest algoritm (icircn sistemele
bazate pe sockeţi există icircn acest scop opţiunea TCP_NODELAY)
Footnotes
algoritm3
Algoritmul aparţinacircnd lui John Nagle a fost propus icircn ianuarie 1984 icircn RFC 896
Fereastra glisantă
Algoritmul implementat de TCP pentru a implementa transferul sigur de date este cunoscut icircn
teorie sub numele de Go-Back-N Icircn acest algoritm se utilizează numere de secvenţă pentru a
distinge pachetele icircntre ele şi o coadă (dimensiunea maximă a cozii reprezintă fereastra) de
pachetele a căror confirmare se aşteaptă Pachetele se icircmpart icircn 4 categorii
1 pachete trimis şi pentru care s-a primit confirmare
2 pachete trimise şi pentru care se aşteaptă icircncă confirmarea
3 pachete care nu au fost trimise icircncă dar care nu depăşesc limitele ferestrei şi deci pot fi
trimise
4 pachete care icircncă nu au fost trimite şi care nici nu vor putea fi trimise decacirct după ce au
fost trimise toate pachetele din categoria 3 şi s-au primit o parte din confirmările la
pachetele din categoria 2
Dacă confirmările pentru pachetele din categoria 2 icircntacircrzie prea mult (un mecanism de timer-e
informează asupra acestui lucru) atunci ele vor fi retrimise Icircn versiunea iniţială TCP-ul nu
permitea decacirct confirmări pozitive ceea ce icircnseamnă că avansarea ferestrei se va icircmpotmoli la
segmentele neconfirmate Cum se poate evita aceasta situaţie vom discuta icircn detaliu icircn capitolele
următoare O soluţie foarte radicală o constituie introducerea de confirmări selective (acest lucru
este realizat de RFC 2018 din octombrie 1996) Această modifică face ca TCP-ul actual să fie un
hibrid de Go-Back-N şi Selective Repeat
Deoarece dimensiunea ferestrei este anunţată la fiecare segment un client lent poate ca pe măsură
ce trimite confirmările să informeze despre progresul icircnregistrat la livrarea datelor următorului
nivel (aplicaţie) Dacă datele vin prea repede pentru viteza cu care clientul procesează datele
fereastra fereastra se va dimiua şi chiar icircnchide (acest lucru se realizează anunţacircnd o fereastră de
dimensiune zero) Cum se realizează efectiv redeschiderea vom analiza icircntr-un capitol viitor
Slow start
Un transfer de date TCP poate să icircnceapă prin transmiterea de segmente pacircnă la umplerea
icircntregii ferestre după care fie se primesc confirmări care vor permite unor noi pachete să fie
trimise fie vor expira timer-ele de retransmisie şi se va icircncepe retrimiterea pachetelor de la
icircnceputul ferestrei Din păcate un astfel de comportament poate duce la pomparea icircn reţea a unui
număr de pachete prea mare pentru capacitatea disponibilă efectiv icircnrăutăţind congestia Pentru
a evita acest lucru s-a propus următoarea soluţie4 iniţial se trimite un segment după primirea
confirmării lui se trimit două segmente după sosirea confirmărilor pentru ele se trimit patru
segmente şi aşa mai departe La un moment dat fie vor icircncepe să se piardă segmente (un indiciu
că s-a atins capacitatea maximă a canalului) fie se va umple fereastra pe care o anunţă cel care
primeşte Trebuie să remarcam că datorită creşterii exponenţiale a numărului de segmente se va
atinge destul de repede una din cele două situaţii
Modalitatea efectivă de implementare a acestui algoritm are la bază utilizarea unei ferestre de
congestie (congestion window cwnd) care este iniţializată cu dimensiunea unui segment (cwnd
se calculează icircn octeţi) şi la fiecare pas este dublată fereastra efectivă din cadrul căreia se pot
trimite segmente este dată de minimul dintre ultima fereastra comunicată de partener şi cwnd
Footnotes
soluţie4
Soluţia aparţine lui V Jacobson şi a fost prezentată icircn 1988 la conferinţă ACM
SIGCOMM-88
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Deoarece TCP trebuie să funcţioneze icircn condiţii variate de latenţă modul icircn care se face
retransmiterea trebuie să fie cacirct mai flexibil (şi simplu icircn acelaşi timp pentru a introduce un
overhead cacirct mai mic) Timpul cacirct se aşteaptă venirea unei confirmări (retransmission timeout
RTO) este calculat prin cronometrarea timpului care icirci ia unui segment trimis să fie confirmat
Pentru o anumită conexiune se cronometrează cacircte un singur segment la un moment dat iar pe
baza RTT-ului măsurat se actualizează valoare RTO-ului
Icircn RFC 793 formula de calcul a RTO-ului este următoarea
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
telefonie clasică cineva formează un număr şi abia icircn momentul icircn care cealaltă persoană
răspunde se poate icircncepe conversaţia Fiind o conexiune host-la-host nu există noţiunile de
broadcast sau multicast
Transferul sigur de date este asigurat icircn următorul mod
Datele sunt icircmpărţite icircn bucăţi a căror dimensiune optimă e determinată de TCP spre
deosebire de UDP care trimite datagrame UDP corespunzătoare cu dimensiunea datelor
primite de la nivelul aplicaţie Unitatea de date trimisă de TCP către nivelul reţea poartă
numele de segment
Cacircnd TCP trimite un segment porneşte un timer şi dacă nu se primeşte confirmarea
segmentului respectiv icircntr-un anumit timp icircl retransmite
Icircn momentul icircn care se primeşte un segment TCP trimite o confirmare (din motive de
eficienţă aceasta poate fi amacircnată un anumit interval de timp)
Icircn headerul TCP este menţinută o sumă de control pentru detectarea modificărilor icircn date
Dacă se recepţionează un segment corupt TCP icircl ignoră urmacircnd să fie retransmis datorită
neprimirii confirmării
Deoarece segmentele TCP sunt transmise mai departe icircncapsulate icircn datagrame IP iar
acestea pot ajunge icircn orice ordine segmentele TCP pot ajunge icircn altă ordine decacirct cea icircn
care au fost trimise De aceea la destinaţie TCP-ul trebuie să se folosească de numere de
secvenţă pentru a reordona eventual segmentele icircnainte de a le livra către nivelul
aplicaţie De asemenea TCP trebuie să asigure ignorarea duplicatelor
TCP asigură controlul fluxului icircn condiţiile icircn care viteza de trimitere a datelor de la sursă
poate fi mult prea mare decacirct capacitatea de prelucrare de la destinaţie
Serviciul oferit de TCP este de tip flux de octeţi deoarece oferă garanţii că fluxul de date trimis
de sursă va fi livrat fără modificări la destinaţie Comparativ UDP-ul produce pentru fiecare
transfer cerut de nivelul aplicaţie un pachet IP (care ulterior poate fi supus fragmentării) care
dacă ajunge la destinaţie corect va fi livrat direct nivelului aplicaţie fără a garanta icircn vreun fel
ordinea
2 Formatul pachetelor TCP
Pachetele de date transmise de TCP segmentele sunt formate dintr-un antet (figura 72) de 20
octeţi urmat de datele primite de la nivelul aplicaţie Antetul poate uneori conţine şi o serie de
opţiuni caz icircn care poate ajunge la 60 octeţi
Figura 72 Structura unui segment TCP
Antetul unui segment TCP cuprinde
port sursă - 16 biţi pentru specificarea portului aplicaţiei transmiţătoare
port destinaţie - 16 biţi pentru specificarea portului aplicaţiei ce recepţionează segmentul
TCP
Aceste două porturi icircmpreună cu adresele ale sursei şi destinaţiei conţinute icircn antet-ul IP
identifică icircn mod unic conexiunea Pentru o pereche formată dintr-o adresă IP şi un port
se foloseşte adesea denumirea de socket (denumire introdusă icircn specificaţiile iniţiale ale
protocolului TCP icircn RFC 793)
număr de secvenţă - 32 biţi
Pentru a asigura un serviciu de tip flux de octeţi TCP numerotează fiecare octet de date
utilizacircnd un număr de secvenţă Numărul de secvenţă din cadrul antetului TCP specifică
destinaţiei care este primul octet din fluxul trimis La iniţierea unei conexiuni se setează
flag-ul SYN şi se alege aleator un număr de secvenţă de icircnceput utilizacircnd un generator de
numere de secvenţă ISN (Initial sequence number) Numărul de secvenţă al primului
octet de date va fi numărul generat ISN plus 1 deoarece pachetul de iniţiere (cu SYN
setat) consumă şi el un număr de secvenţă Se va vedea mai departe că şi flag-ul de
terminare a conexiunii FIN consumă şi el un număr de secvenţă
confirmare - 32 biţi
Reprezintă numărul de secvenţă al octetului de date pe care transmiţătorul confirmării se
aşteaptă să-l primească Astfel dacă s-a recepţionat octetul cu numărul de secvenţă x (icircn
numerotaţia sursei) pachetul de confirmare va avea flag-ul ACK setat şi va conţine
numărul de confirmare x + 1 Trimiterea unui ACK nu consumă un număr de secvenţă
deoarece atacirct acest cacircmp cacirct şi flag-ul ACK fac parte din antet şi după stabilirea
conexiunii ambele cacircmpuri devin active Acest mecanism nu permite confirmări selective
pentru că numărul de secvenţă specifică pacircnă unde s-au recepţionat date De exemplu
dacă la destinaţie au ajuns octeţii 1-1024 şi următorul segment primit conţine octeţii
2049-3072 nu se poate trimite confirmare pentru cel de-al doilea segment deci
confirmarea va cuprinde numărul de secvenţă 1025
lungimea antetului - 4 biţi
Specifică dimensiunea antetului ca număr de cuvinte de 32 de biţi (4 octeţi) Antetul
poate avea icircntre 20 şi 60 de octeţi deci valoarea acestui cacircmp va fi icircntre 5 (5 x 4 = 20
octeţi) şi 15 (15 x 4 = 60)
6 biţi rezervaţi pentru utilizări viitoare
6 biţi de control reprezentacircnd următoarele flag-uri ce pot fi setate simultan
o URG - cacircmpul urgent pointer este valid
o ACK - cacircmpul de confirmare este valid
o PSH - destinaţia trebuie să trimită datele către nivelul aplicaţie cacirct mai devreme
o RST - se doreşte resetarea conexiunii
o SYN - iniţierea conexiunii
o FIN - icircnchiderea conexiunii
dimensiunea ferestrei - 16 biţi
Reprezintă numărul de octeţi (icircncepacircnd cu numărul de secvenţă conţinut icircn cacircmpul de
confirmare) pe care destinaţia e dispusă să-l primească Este limitat la 65535 octeţi dar
cu toate că pare o limită destul de mare există situaţii cacircnd se doresc valori mult mai
mari Icircn acest scop se folosesc nişte opţiuni speciale descrise ceva mai tacircrziu care permit
scalarea ferestrei
suma de control - 16 biţi
Această sumă de control acoperă icircntregul segment TCP (atacirct datele cacirct şi antetul TCP) şi
spre deosebire de UDP este obligatoriu să fie completat de transmiţător şi verificat de
receptor Dar ca şi icircn cazul UDP-ului la calculul sumei de control se ia in considerare şi
o zona specială de 12 octeţi ce cuprinde pentru re-verificare cacircmpuri din antetul IP
(adresa IP a sursei şi a destinaţiei)[aici tre sa vina o referire la poza cu pseudo-antetu]
După adăugarea acestui pseudo-antet datele se icircmpart icircn cuvinte de 16 biţi icircn vederea
calculării sumei de control adăugacircndu-se eventual şi un octet de aliniere
urgent pointer - 16 biţi
Este utilizat pentru specificarea deplasamentului ultimului octet de date trimis icircn regim
urgent Astfel ultimul octet din secvenţa urgentă se obţine adunacircnd acest cacircmp la
numărul de secvenţă Ce icircnseamnă acest mod urgent de transmitere există situaţii icircn care
aplicaţiile vor să trimită date `neordonate` Să presupunem că aplicaţia a trimis către
nivelul transport o cantitate mare de date dar la un moment dat observă ceva icircn neregulă
şi doreşte să anuleze operaţia Dacă trimite o comandă de anulare aceasta va fi adăugată
la sfacircrşitul şirului de octeţi deci nu se va putea icircmpiedica ajungerea acestora la nivelul
aplicaţie de la receptor Activacircnd modul urgent datele urgente (comanda de anulare) vor
fi plasate la icircnceputul pachetului Aplicaţiile mai cunoscute care folosesc acest mod sunt
Telnet Rlogin şi FTP
opţiuni - pacircnă la 40 de octeţi (figura 73)
Cele mai utilizate opţiuni sunt
o Sfacircrşit de opţiuni (end of option) - 1 octet
Este utilizat pentru alinierea datelor conţinute icircn cacircmpul de opţiuni Nu poate fi
utilizat decacirct o singură dată marcacircndu-se astfel sfacircrşitul opţiunilor şi icircnceperea
datelor efective Dacă pentru alinierea la un cuvacircnt de 32 de biţi e nevoie de mai
mult de 1 byte se va utiliza opţiunea no operation Orice apare după această
opţiune pacircnă la icircnceputul cuvacircntului următor de 32 de biţi e ignorat
o no operation - 1 octet
Utilizat pentru alinierea la cuvinte de 32 de biţi
o Dimensiunea maximă a segmentului (Maximum Segment Size (MSS)) - 16 biţi
Icircn ciuda denumirii defineşte lungimea maximă a datelor nu dimensiunea
icircntregului segment Poate lua valori icircntre 0 şi 65535 valoarea implicită fiind 536
Această opţiune e valabilă doar icircn pachetele de iniţiere a conexiunii (cele cu flag-
ul SYN setat) fiecare parte făcacircnd cunoscută dimensiunea maximă a datelor
dispusă să le primească icircntr-un pachet Icircn principiu cu cacirct această valoarea e mai
mare e mai bine (deoarece se recuperează din spaţiul ocupat de antetele TCP şi
IP) pacircnă cacircnd apare fragmentarea Valoarea maximă la care se poate seta este
MTU (Maximum Transfer Unit) minus dimensiunea antetului IP şi TCP (1460
octeţi icircn cazul Ethernet)
o Factor de scalare a ferestrei (Window scale factor) - 1 octet
Pentru situaţiile icircn care se doreşte utilizarea unei ferestre mai mare de 65535 bytes
se poate utiliza acest cacircmp pentru mărirea dimensiunii ferestrei Noua dimensiune
va fi Chiar dacă
factorul de scalare poate fi maxim 255 icircn cazul TCPIP el nu poate depăşi
valoarea 16 deoarece dimensiunea maximă a ferestrei nu poate fi mai mare decacirct
valoarea celui mai mare număr de secvenţă ( )
Acest factor se poate seta doar la iniţierea conexiunii Icircn timpul transferului de
date se poate modifica dimensiunea ferestrei dar factorul de scalare rămacircne
acelaşi Dacă cel care a iniţiat conexiunea a trimis icircn segmentul de iniţiere şi acest
factor dar icircn pachetul cu ACK destinatarul nu şi-a trimis şi el factorul atunci se la
considera 0 icircn ambele direcţii Invers dacă cel care solicită deschiderea
conexiunii nu setează factorul destinaţia nu va putea seta factorul de scalare
o Timestamp - 10 octeţi
Utilizat pentru reţinerea timpului icircn vederea calculării RTT (Round Trip Time)
Cacircmpul timestamp e completat de sursă icircn momentul trimiterii segmentului La
destinaţie valoarea este reţinută şi copiată icircn cacircmpul timestamp echo reply al
pachetului cu confirmarea RTT-ul este calculat de sursă făcacircnd diferenţa dintre
timpul curent şi această valoare
Figura Opţiuni TCP
3 Iniţierea şi terminarea unei conexiuni TCP
TCP este un protocol orientat conexiune deci presupune stabilirea unei căi virtuale icircntre sursă şi
destinaţie
Subsections
Protocolul de iniţiere
o 1 Deschiderea simultană
Protocolul de terminare
o 2 Terminarea simultană
o 3 Resetarea conexiunii
Diagrama de stări
Protocolul de iniţiere
Modul de transmisie icircn cazul protocolului TCP este full-duplex deci sunt transmise date
simultan icircn ambele direcţii Aceasta presupune că cel care iniţiază conexiunea trebuie să
primească aprobarea celuilalt capăt icircnainte de icircnceperea transferului de date sursa icircşi anunţă
intenţia de a iniţia o conexiune destinaţia trimite un pachet cu confirmarea cererii şi un pachet de
iniţiere a conexiunii de la el la sursă iar apoi sursa confirmă cererea primită de la destinaţie Paşii
2 şi 3 pot fi realizaţi prin trimiterea unui singur pachet de aceea protocolul de iniţiere este
cunoscut sub numele de three-way handshake
Icircn cadrul protocolului de iniţiere există 2 tipuri de cereri de iniţiere cerere activă (active open)
iniţiată de clientul ce doreşte să stabilească conexiunea cu serverul şi cerere pasivă (passive
open) din partea serverului
Cei 3 paşi sunt
1 Clientul trimite un segment cu flag-ul SYN setat şi care conţine portul sursă portul de la
destinaţie şi numărul de secvenţă generat iniţial (ISN) de la care se vor numerota octeţii
de la client către server Opţional se pot stabili parametrii conexiunii prin setarea lungimii
maxime a segmentelor (MSS) dispus să le primească de la server factorului de scalare a
ferestrei Acest prim segment nu conţine nici un parametru de confirmare şi de asemenea
nu are rost să conţine să seteze dimensiunea ferestrei
2 Al doilea segment e trimis de server şi are un rol dublu confirmă segmentul primit de la
client prin setarea flag-ului ACK şi completează numărul de secvenţă cu numărul de
secvenţă primit plus 1 şi al doilea rol iniţializează conexiunea de la el către client prin
setarea flag-ului SYN şi generarea unui număr de secvenţă iniţial ce va fi folosit icircn
numerotarea octeţilor de la server spre client Pe lacircngă aceasta trebuie să conţină
dimensiunea ferestrei şi opţional poate seta factorul de scalare şi dimensiunea maximă a
segmentului acceptat
3 Clientul trimite un segment cu confirmarea cererii din partea serverului (ACK setat +
completează numărul confirmat cu numărul de secvenţa primit + 1) Ca şi icircn cazul
pasului 2 trebuie să seteze dimensiunea ferestrei Acest pachet poate conţine date
Subsections
1 Deschiderea simultană
1 Deschiderea simultană
Se poate icircntacircmpla ca uneori cele două capete care vor să comunice să icircncerce să stabilească
conexiunea simultan Icircn acest caz după ce fiecare a trimis segmentul de iniţiere (iniţiere activă)
ambele vor trimite un segment cu SYN + ACK şi se va stabili o singură conexiune nu două
Protocolul de terminare
Oricare dintre cele două părţi poate solicita icircnchiderea conexiunii dar conexiunea fiind full-
duplex transferul de date icircn celălalt sens poate continua (această situaţie e denumită half-close)
O icircnchidere completă a unei conexiuni TCP presupune următorii paşi
1 Clientul trimite un segment cu flag-ul FIN activat solicitacircnd icircnchiderea conexiunii
2 Serverul trimite un segment ACK confirmacircnd primirea cererea Numărul de confirmare
se completează normal ca numărul de secvenţă primit + 1
3 Serverul continuă să trimită date către client şi cacircnd doreşte să icircnchidă şi el conexiunea
trimite un segment cu FIN activat
4 Clientul trimite un pachet ACK confirmacircnd icircnchiderea conexiunii
Cel care iniţiază primul procedura de icircnchidere (trimite primul FIN) realizează o icircnchidere activă
(active close) iar celălalt capăt o icircnchidere pasivă (passive close) Icircn mod normal cel care
realizează iniţierea activă va fi primul ce va trimite FIN dar oricare dintre cei doi poate icircnchide
activ conexiunea
Subsections
2 Terminarea simultană
3 Resetarea conexiunii
2 Terminarea simultană
Icircn mod similar cu deschiderea simultană există posibilitatea ca ambele capete ale conexiunii TCP
să iniţieze simultan procedura de icircnchidere a conexiunii Icircn acest caz ambele părţi vor trimite
FIN şi vor aştepta primirea unui ACK Icircn continuare fiecare va primi cererea de terminare şi va
trimite ACK Se observă că numărul de segmente transferate pentru realizarea icircnchiderii
conexiunii (4 segmente) este acelaşi ca la terminarea normală
3 Resetarea conexiunii
Există situaţii icircn care TCP doreşte resetarea conexiunii De exemplu dacă se solicită iniţierea
unei conexiuni la un port inexistent Icircn acest caz cealaltă parte va trimite un segment cu bitul
RST setat pentru a anula solicitarea O altă situaţie este atunci cacircnd se constată că celalalt capăt
al conexiunii nu răspunde un anumit timp (timeout)
Diagrama de stări
Toate evenimentele ce au loc icircn timpul stabilirii conexiunii transferului şi icircnchiderii conexiunii
pot fi rezumate printr-un automat finit cunoscut sub numele de diagrama de stări După cum
chiar numele sugerează este o maşină cu un număr limitat de stări O stare este păstrată pacircnă icircn
momentul apariţiei unui eveniment moment icircn care se poate trece icircn altă stare şisau efectua o
acţiune
Aceste stări posibile sunt (denumirile sunt asemănătoare cu cele utilizate de netstat) cele din
tabelul 71
Tabela Stările diagramei de stări TCP
Stare Descriere
CLOSED Nu există conexiune
LISTEN Serverul aşteaptă cereri de la clienţi
SYN_SENT Cerere de iniţiere (activă) a conexiunii Se
aşteaptă confirmarea
SYN_RCVD S-a primit o cerere de iniţiere conexiune
ESTABLISHED S-a stabilit conexiunea
FIN_WAIT_1 Aplicaţia a solicitat icircnchiderea conexiunii
FIN_WAIT_2 Serverul a acceptat icircnchiderea conexiunii
CLOSING Ambele părţi solicită simultan icircnchiderea
conexiunii
TIME_WAIT Conexiune icircnchisă dar se aşteaptă ca
pachetele retransmise să dispară
CLOSE_WAIT Serverul aşteaptă icircnchiderea dinspre partea
aplicaţiei
LAST_ACK Serverul a icircnchis conexiunea Aşteaptă
ultima confirmare
Icircn diagrama ilustrată icircn figura 74 putem observa 3 tipuri de tranziţii icircntre cele 11 stări tranziţii
ce corespund unei funcţionări normale pentru client (linii normale continue) pentru server (linii
normale icircntrerupte) şi tranziţii pentru situaţii nestandard (linii subţiri continue)
O comportarea normală pentru client presupune parcurgerea următoarelor stări CLOSED
SYN_SEND ESTABLISHED FIN_WAY_1 FIN_WAY_2 TIME_WAIT
Iniţial clientul TCP se află icircn starea CLOSED
Aşteptacircnd icircn starea CLOSED clientul poate primi de la aplicaţie o cerere de iniţiere
activă a unei conexiuni Trimite un segment SYN şi trece icircn starea SYN_SENT
Icircn starea SYN_SENT clientul aşteaptă de la server un segment ACK+SYN după care
trimite un ACK şi trece icircn starea ESTABLISHED Din acest moment poate icircncepe
transferul efectiv de date Clientul va rămacircne icircn această stare cacirct timp are de trimisprimit
date
Aflat icircn această stare clientul TCP poate primi din partea aplicaţiei o cerere de icircnchidere a
conexiunii Icircn acest caz va trimit un segment FIN şi trece icircn starea FIN_WAIT_1
Icircn această stare clientul aşteaptă ACK din partea serverului După ce-l primeşte
conexiunea icircntr-un sens se va icircnchide şi clientul trece icircn starea FIN_WAIT_2
Starea FIN_WAIT_2 durează pacircnă cacircnd primeşte cererea de icircnchidere a conexiunii FIN
din partea serverului Trimite ACK şi va trece icircn starea TIME_WAIT
Icircn această stare se va porni un timer cu valoarea setată la dublul timpului de viaţă estimat
pentru un segment de lungime maximă MSL (Maximum Segment Lifetime) Acest timer
permite retransmiterea ACK-ului icircn cazul icircn care acesta se pierde (celălalt capăt va da
timeout şi va retransmite segmentul FIN) Icircn tot acest time cei doi sockeţi (de la client şi
server) nu vor putea fi reutilizaţi Totodată pachetele icircntacircrziate care sosesc icircn această
perioadă sunt ignorate După expirarea acestui timer clientul revine icircn starea iniţială
CLOSED
Din punctul de vedere al unui server o comportare standard parcurge următoarele stări
CLOSED LISTEN SYN_RCVD ESTABLISHED CLOSE_WAIT şi LAST_ACK
Iniţial serverul TCP se află icircn starea CLOSED
Icircn această stare poate primi de la aplicaţia server o cerere de iniţiere activă şi trece icircn
starea LISTEN
Aflat icircn starea LISTEN serverului TCP poate recepţiona un segment SYN de la un client
TCP Icircn acest caz va trimite ACK+SYN şi va trece icircn starea SYN_RCVD
Icircn această stare serverul aşteaptă primirea confirmării de la client moment icircn care
conexiunea e stabilită icircn ambele sensuri şi se poate icircncepe transferul de date (starea
ESTABLISHED)
Clientul TCP poate solicita icircnchiderea conexiunii trimiţacircnd un segment FIN către server
Icircn acest caz serverul TCP trimite confirmarea şi trece icircn starea CLOSE_WAIT
Icircn această stare serverul aşteaptă să primească din partea programului server icircnchiderea
conexiunii moment icircn care va trimite către client un segment FIN şi trece icircn starea
LAST_ACK
Serverul aşteaptă primirea ultimei confirmări de la client după care revine icircn starea
CLOSED
Atacirct serverul cacirct şi clientul TCP se pot afla icircn oricare din cele 11 stări ale diagramei
Figura Diagrama de stări pentru TCP
4 Controlul fluxului
Dacă icircncă de la icircnceput s-a reuşit stabilirea formatului unui pachet TCP şi a modulului icircn care
trebuie să se facă icircnchiderea şi deschiderea unei conexiuni nu acelaşi lucru se poate spune şi
despre modul icircn care ar trebui să se realizeze controlul fluxului Ţinacircnd seama icircnsă că din 1989
(de cacircnd datează RFC-ul 2581 cel despre care am menţionat că specifică icircn mod clar modul icircn
care trebuie să se comporte o implementare de TCP) TCP-ul a rămas neschimbat putem să icircl
considerăm un rezultat important al domeniului reţelor de calculatoare
Icircn cele ce urmează vom icircnţelege prin controlul fluxului totalitatea algoritmilor care permit
atingerea unei viteze de transfer punct-la-punct cacirct mai mare pentru toate conexiunile existente
Icircn principal aceşti algoritmi stabilesc modul icircn care segmentele şi confirmările trebuie trimise şi
ce acţiuni trebuie executate icircn situaţiile icircn care răspunsurile aşteptate de la celălalt capăt icircntacircrzie
să vină
Subsections
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
Icircntacircrzierea confirmărilor
O modalitate simplă de generare a confirmărilor este de a trimite cacircte una pentru fiecare segment
primit Această politică prezintă avantajul de a face comunicaţia self-clocking icircnsă este
ineficientă dacă segmentele care nu conţin decacirct confirmări sunt urmate la scurtă distanţă (cacircteva
zeci de milisecunde) de segmente ce conţin date efective Pentru a evita această situaţie se
procedează2 la icircntacircrzierea (200ms este o valoare uzuală icircn RFC 1122 se specifică o valoare
maximă de 500ms) a segmentelor care conţin doar confirmări Această strategie face posibil ca
un răspuns generat de primirea unor date să plece sper celălalt capăt icircn acelaşi segment cu
confirmarea
Observaţie deoarece este dificil de menţinut timere pentru fiecare confirmare diferenţa de
200ms este calculată de un timer global Din acest motiv modul efectiv de comportare poate fi
descris şi icircn felul următor cacircnd un segment nu conţine decacirct o confirmare el este pus icircntr-o
coadă ce va fi inspectată de un proces care din 200 icircn 200 ms trimite tot ce s-a acumulat icircn
coada
Footnotes
2
Acest comportament a fost propus de David D Clark icircn iulie 1982 icircn RFC 813
Algoritmul Nagle
Acest algoritm3 icircncearcă să icircmbunătăţească performanţele exploatacircnd următoarea caracteristică
foarte des icircntacirclnită icircn dialogul dintre două staţii dacă se icircncearcă trimiterea unor date de
dimensiune mică icircnsă există icircncă date neconfirmate de partener atunci ele sunt buffer-ate şi
trimise icircntr-un segment mai mare cacircnd soseşte confirmarea aşteptată Icircn acest fel se poate evita
generarea datagramelor mici (tinygrame) icircn situaţia unei legături lente Icircn cazul unei legături
rapide confirmările vor veni repede şi icircntacircrzierea introdusă de algoritm va neglijabilă
Există icircnsă şi cazuri icircn care acest algoritm duce la deprecierea performanţelor mesajele scurte
generate de mişcările mouse-ului icircn cazul folosirii unui server X Window sau utilizarea tastelor
care trimit mai mult de un caracter (secvenţe escape) Pentru a rezolva aceste inconveninte API-
ul de utilizare a TCP-ului trebuie să ofere o modalitate de a dezactiva acest algoritm (icircn sistemele
bazate pe sockeţi există icircn acest scop opţiunea TCP_NODELAY)
Footnotes
algoritm3
Algoritmul aparţinacircnd lui John Nagle a fost propus icircn ianuarie 1984 icircn RFC 896
Fereastra glisantă
Algoritmul implementat de TCP pentru a implementa transferul sigur de date este cunoscut icircn
teorie sub numele de Go-Back-N Icircn acest algoritm se utilizează numere de secvenţă pentru a
distinge pachetele icircntre ele şi o coadă (dimensiunea maximă a cozii reprezintă fereastra) de
pachetele a căror confirmare se aşteaptă Pachetele se icircmpart icircn 4 categorii
1 pachete trimis şi pentru care s-a primit confirmare
2 pachete trimise şi pentru care se aşteaptă icircncă confirmarea
3 pachete care nu au fost trimise icircncă dar care nu depăşesc limitele ferestrei şi deci pot fi
trimise
4 pachete care icircncă nu au fost trimite şi care nici nu vor putea fi trimise decacirct după ce au
fost trimise toate pachetele din categoria 3 şi s-au primit o parte din confirmările la
pachetele din categoria 2
Dacă confirmările pentru pachetele din categoria 2 icircntacircrzie prea mult (un mecanism de timer-e
informează asupra acestui lucru) atunci ele vor fi retrimise Icircn versiunea iniţială TCP-ul nu
permitea decacirct confirmări pozitive ceea ce icircnseamnă că avansarea ferestrei se va icircmpotmoli la
segmentele neconfirmate Cum se poate evita aceasta situaţie vom discuta icircn detaliu icircn capitolele
următoare O soluţie foarte radicală o constituie introducerea de confirmări selective (acest lucru
este realizat de RFC 2018 din octombrie 1996) Această modifică face ca TCP-ul actual să fie un
hibrid de Go-Back-N şi Selective Repeat
Deoarece dimensiunea ferestrei este anunţată la fiecare segment un client lent poate ca pe măsură
ce trimite confirmările să informeze despre progresul icircnregistrat la livrarea datelor următorului
nivel (aplicaţie) Dacă datele vin prea repede pentru viteza cu care clientul procesează datele
fereastra fereastra se va dimiua şi chiar icircnchide (acest lucru se realizează anunţacircnd o fereastră de
dimensiune zero) Cum se realizează efectiv redeschiderea vom analiza icircntr-un capitol viitor
Slow start
Un transfer de date TCP poate să icircnceapă prin transmiterea de segmente pacircnă la umplerea
icircntregii ferestre după care fie se primesc confirmări care vor permite unor noi pachete să fie
trimise fie vor expira timer-ele de retransmisie şi se va icircncepe retrimiterea pachetelor de la
icircnceputul ferestrei Din păcate un astfel de comportament poate duce la pomparea icircn reţea a unui
număr de pachete prea mare pentru capacitatea disponibilă efectiv icircnrăutăţind congestia Pentru
a evita acest lucru s-a propus următoarea soluţie4 iniţial se trimite un segment după primirea
confirmării lui se trimit două segmente după sosirea confirmărilor pentru ele se trimit patru
segmente şi aşa mai departe La un moment dat fie vor icircncepe să se piardă segmente (un indiciu
că s-a atins capacitatea maximă a canalului) fie se va umple fereastra pe care o anunţă cel care
primeşte Trebuie să remarcam că datorită creşterii exponenţiale a numărului de segmente se va
atinge destul de repede una din cele două situaţii
Modalitatea efectivă de implementare a acestui algoritm are la bază utilizarea unei ferestre de
congestie (congestion window cwnd) care este iniţializată cu dimensiunea unui segment (cwnd
se calculează icircn octeţi) şi la fiecare pas este dublată fereastra efectivă din cadrul căreia se pot
trimite segmente este dată de minimul dintre ultima fereastra comunicată de partener şi cwnd
Footnotes
soluţie4
Soluţia aparţine lui V Jacobson şi a fost prezentată icircn 1988 la conferinţă ACM
SIGCOMM-88
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Deoarece TCP trebuie să funcţioneze icircn condiţii variate de latenţă modul icircn care se face
retransmiterea trebuie să fie cacirct mai flexibil (şi simplu icircn acelaşi timp pentru a introduce un
overhead cacirct mai mic) Timpul cacirct se aşteaptă venirea unei confirmări (retransmission timeout
RTO) este calculat prin cronometrarea timpului care icirci ia unui segment trimis să fie confirmat
Pentru o anumită conexiune se cronometrează cacircte un singur segment la un moment dat iar pe
baza RTT-ului măsurat se actualizează valoare RTO-ului
Icircn RFC 793 formula de calcul a RTO-ului este următoarea
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
Figura 72 Structura unui segment TCP
Antetul unui segment TCP cuprinde
port sursă - 16 biţi pentru specificarea portului aplicaţiei transmiţătoare
port destinaţie - 16 biţi pentru specificarea portului aplicaţiei ce recepţionează segmentul
TCP
Aceste două porturi icircmpreună cu adresele ale sursei şi destinaţiei conţinute icircn antet-ul IP
identifică icircn mod unic conexiunea Pentru o pereche formată dintr-o adresă IP şi un port
se foloseşte adesea denumirea de socket (denumire introdusă icircn specificaţiile iniţiale ale
protocolului TCP icircn RFC 793)
număr de secvenţă - 32 biţi
Pentru a asigura un serviciu de tip flux de octeţi TCP numerotează fiecare octet de date
utilizacircnd un număr de secvenţă Numărul de secvenţă din cadrul antetului TCP specifică
destinaţiei care este primul octet din fluxul trimis La iniţierea unei conexiuni se setează
flag-ul SYN şi se alege aleator un număr de secvenţă de icircnceput utilizacircnd un generator de
numere de secvenţă ISN (Initial sequence number) Numărul de secvenţă al primului
octet de date va fi numărul generat ISN plus 1 deoarece pachetul de iniţiere (cu SYN
setat) consumă şi el un număr de secvenţă Se va vedea mai departe că şi flag-ul de
terminare a conexiunii FIN consumă şi el un număr de secvenţă
confirmare - 32 biţi
Reprezintă numărul de secvenţă al octetului de date pe care transmiţătorul confirmării se
aşteaptă să-l primească Astfel dacă s-a recepţionat octetul cu numărul de secvenţă x (icircn
numerotaţia sursei) pachetul de confirmare va avea flag-ul ACK setat şi va conţine
numărul de confirmare x + 1 Trimiterea unui ACK nu consumă un număr de secvenţă
deoarece atacirct acest cacircmp cacirct şi flag-ul ACK fac parte din antet şi după stabilirea
conexiunii ambele cacircmpuri devin active Acest mecanism nu permite confirmări selective
pentru că numărul de secvenţă specifică pacircnă unde s-au recepţionat date De exemplu
dacă la destinaţie au ajuns octeţii 1-1024 şi următorul segment primit conţine octeţii
2049-3072 nu se poate trimite confirmare pentru cel de-al doilea segment deci
confirmarea va cuprinde numărul de secvenţă 1025
lungimea antetului - 4 biţi
Specifică dimensiunea antetului ca număr de cuvinte de 32 de biţi (4 octeţi) Antetul
poate avea icircntre 20 şi 60 de octeţi deci valoarea acestui cacircmp va fi icircntre 5 (5 x 4 = 20
octeţi) şi 15 (15 x 4 = 60)
6 biţi rezervaţi pentru utilizări viitoare
6 biţi de control reprezentacircnd următoarele flag-uri ce pot fi setate simultan
o URG - cacircmpul urgent pointer este valid
o ACK - cacircmpul de confirmare este valid
o PSH - destinaţia trebuie să trimită datele către nivelul aplicaţie cacirct mai devreme
o RST - se doreşte resetarea conexiunii
o SYN - iniţierea conexiunii
o FIN - icircnchiderea conexiunii
dimensiunea ferestrei - 16 biţi
Reprezintă numărul de octeţi (icircncepacircnd cu numărul de secvenţă conţinut icircn cacircmpul de
confirmare) pe care destinaţia e dispusă să-l primească Este limitat la 65535 octeţi dar
cu toate că pare o limită destul de mare există situaţii cacircnd se doresc valori mult mai
mari Icircn acest scop se folosesc nişte opţiuni speciale descrise ceva mai tacircrziu care permit
scalarea ferestrei
suma de control - 16 biţi
Această sumă de control acoperă icircntregul segment TCP (atacirct datele cacirct şi antetul TCP) şi
spre deosebire de UDP este obligatoriu să fie completat de transmiţător şi verificat de
receptor Dar ca şi icircn cazul UDP-ului la calculul sumei de control se ia in considerare şi
o zona specială de 12 octeţi ce cuprinde pentru re-verificare cacircmpuri din antetul IP
(adresa IP a sursei şi a destinaţiei)[aici tre sa vina o referire la poza cu pseudo-antetu]
După adăugarea acestui pseudo-antet datele se icircmpart icircn cuvinte de 16 biţi icircn vederea
calculării sumei de control adăugacircndu-se eventual şi un octet de aliniere
urgent pointer - 16 biţi
Este utilizat pentru specificarea deplasamentului ultimului octet de date trimis icircn regim
urgent Astfel ultimul octet din secvenţa urgentă se obţine adunacircnd acest cacircmp la
numărul de secvenţă Ce icircnseamnă acest mod urgent de transmitere există situaţii icircn care
aplicaţiile vor să trimită date `neordonate` Să presupunem că aplicaţia a trimis către
nivelul transport o cantitate mare de date dar la un moment dat observă ceva icircn neregulă
şi doreşte să anuleze operaţia Dacă trimite o comandă de anulare aceasta va fi adăugată
la sfacircrşitul şirului de octeţi deci nu se va putea icircmpiedica ajungerea acestora la nivelul
aplicaţie de la receptor Activacircnd modul urgent datele urgente (comanda de anulare) vor
fi plasate la icircnceputul pachetului Aplicaţiile mai cunoscute care folosesc acest mod sunt
Telnet Rlogin şi FTP
opţiuni - pacircnă la 40 de octeţi (figura 73)
Cele mai utilizate opţiuni sunt
o Sfacircrşit de opţiuni (end of option) - 1 octet
Este utilizat pentru alinierea datelor conţinute icircn cacircmpul de opţiuni Nu poate fi
utilizat decacirct o singură dată marcacircndu-se astfel sfacircrşitul opţiunilor şi icircnceperea
datelor efective Dacă pentru alinierea la un cuvacircnt de 32 de biţi e nevoie de mai
mult de 1 byte se va utiliza opţiunea no operation Orice apare după această
opţiune pacircnă la icircnceputul cuvacircntului următor de 32 de biţi e ignorat
o no operation - 1 octet
Utilizat pentru alinierea la cuvinte de 32 de biţi
o Dimensiunea maximă a segmentului (Maximum Segment Size (MSS)) - 16 biţi
Icircn ciuda denumirii defineşte lungimea maximă a datelor nu dimensiunea
icircntregului segment Poate lua valori icircntre 0 şi 65535 valoarea implicită fiind 536
Această opţiune e valabilă doar icircn pachetele de iniţiere a conexiunii (cele cu flag-
ul SYN setat) fiecare parte făcacircnd cunoscută dimensiunea maximă a datelor
dispusă să le primească icircntr-un pachet Icircn principiu cu cacirct această valoarea e mai
mare e mai bine (deoarece se recuperează din spaţiul ocupat de antetele TCP şi
IP) pacircnă cacircnd apare fragmentarea Valoarea maximă la care se poate seta este
MTU (Maximum Transfer Unit) minus dimensiunea antetului IP şi TCP (1460
octeţi icircn cazul Ethernet)
o Factor de scalare a ferestrei (Window scale factor) - 1 octet
Pentru situaţiile icircn care se doreşte utilizarea unei ferestre mai mare de 65535 bytes
se poate utiliza acest cacircmp pentru mărirea dimensiunii ferestrei Noua dimensiune
va fi Chiar dacă
factorul de scalare poate fi maxim 255 icircn cazul TCPIP el nu poate depăşi
valoarea 16 deoarece dimensiunea maximă a ferestrei nu poate fi mai mare decacirct
valoarea celui mai mare număr de secvenţă ( )
Acest factor se poate seta doar la iniţierea conexiunii Icircn timpul transferului de
date se poate modifica dimensiunea ferestrei dar factorul de scalare rămacircne
acelaşi Dacă cel care a iniţiat conexiunea a trimis icircn segmentul de iniţiere şi acest
factor dar icircn pachetul cu ACK destinatarul nu şi-a trimis şi el factorul atunci se la
considera 0 icircn ambele direcţii Invers dacă cel care solicită deschiderea
conexiunii nu setează factorul destinaţia nu va putea seta factorul de scalare
o Timestamp - 10 octeţi
Utilizat pentru reţinerea timpului icircn vederea calculării RTT (Round Trip Time)
Cacircmpul timestamp e completat de sursă icircn momentul trimiterii segmentului La
destinaţie valoarea este reţinută şi copiată icircn cacircmpul timestamp echo reply al
pachetului cu confirmarea RTT-ul este calculat de sursă făcacircnd diferenţa dintre
timpul curent şi această valoare
Figura Opţiuni TCP
3 Iniţierea şi terminarea unei conexiuni TCP
TCP este un protocol orientat conexiune deci presupune stabilirea unei căi virtuale icircntre sursă şi
destinaţie
Subsections
Protocolul de iniţiere
o 1 Deschiderea simultană
Protocolul de terminare
o 2 Terminarea simultană
o 3 Resetarea conexiunii
Diagrama de stări
Protocolul de iniţiere
Modul de transmisie icircn cazul protocolului TCP este full-duplex deci sunt transmise date
simultan icircn ambele direcţii Aceasta presupune că cel care iniţiază conexiunea trebuie să
primească aprobarea celuilalt capăt icircnainte de icircnceperea transferului de date sursa icircşi anunţă
intenţia de a iniţia o conexiune destinaţia trimite un pachet cu confirmarea cererii şi un pachet de
iniţiere a conexiunii de la el la sursă iar apoi sursa confirmă cererea primită de la destinaţie Paşii
2 şi 3 pot fi realizaţi prin trimiterea unui singur pachet de aceea protocolul de iniţiere este
cunoscut sub numele de three-way handshake
Icircn cadrul protocolului de iniţiere există 2 tipuri de cereri de iniţiere cerere activă (active open)
iniţiată de clientul ce doreşte să stabilească conexiunea cu serverul şi cerere pasivă (passive
open) din partea serverului
Cei 3 paşi sunt
1 Clientul trimite un segment cu flag-ul SYN setat şi care conţine portul sursă portul de la
destinaţie şi numărul de secvenţă generat iniţial (ISN) de la care se vor numerota octeţii
de la client către server Opţional se pot stabili parametrii conexiunii prin setarea lungimii
maxime a segmentelor (MSS) dispus să le primească de la server factorului de scalare a
ferestrei Acest prim segment nu conţine nici un parametru de confirmare şi de asemenea
nu are rost să conţine să seteze dimensiunea ferestrei
2 Al doilea segment e trimis de server şi are un rol dublu confirmă segmentul primit de la
client prin setarea flag-ului ACK şi completează numărul de secvenţă cu numărul de
secvenţă primit plus 1 şi al doilea rol iniţializează conexiunea de la el către client prin
setarea flag-ului SYN şi generarea unui număr de secvenţă iniţial ce va fi folosit icircn
numerotarea octeţilor de la server spre client Pe lacircngă aceasta trebuie să conţină
dimensiunea ferestrei şi opţional poate seta factorul de scalare şi dimensiunea maximă a
segmentului acceptat
3 Clientul trimite un segment cu confirmarea cererii din partea serverului (ACK setat +
completează numărul confirmat cu numărul de secvenţa primit + 1) Ca şi icircn cazul
pasului 2 trebuie să seteze dimensiunea ferestrei Acest pachet poate conţine date
Subsections
1 Deschiderea simultană
1 Deschiderea simultană
Se poate icircntacircmpla ca uneori cele două capete care vor să comunice să icircncerce să stabilească
conexiunea simultan Icircn acest caz după ce fiecare a trimis segmentul de iniţiere (iniţiere activă)
ambele vor trimite un segment cu SYN + ACK şi se va stabili o singură conexiune nu două
Protocolul de terminare
Oricare dintre cele două părţi poate solicita icircnchiderea conexiunii dar conexiunea fiind full-
duplex transferul de date icircn celălalt sens poate continua (această situaţie e denumită half-close)
O icircnchidere completă a unei conexiuni TCP presupune următorii paşi
1 Clientul trimite un segment cu flag-ul FIN activat solicitacircnd icircnchiderea conexiunii
2 Serverul trimite un segment ACK confirmacircnd primirea cererea Numărul de confirmare
se completează normal ca numărul de secvenţă primit + 1
3 Serverul continuă să trimită date către client şi cacircnd doreşte să icircnchidă şi el conexiunea
trimite un segment cu FIN activat
4 Clientul trimite un pachet ACK confirmacircnd icircnchiderea conexiunii
Cel care iniţiază primul procedura de icircnchidere (trimite primul FIN) realizează o icircnchidere activă
(active close) iar celălalt capăt o icircnchidere pasivă (passive close) Icircn mod normal cel care
realizează iniţierea activă va fi primul ce va trimite FIN dar oricare dintre cei doi poate icircnchide
activ conexiunea
Subsections
2 Terminarea simultană
3 Resetarea conexiunii
2 Terminarea simultană
Icircn mod similar cu deschiderea simultană există posibilitatea ca ambele capete ale conexiunii TCP
să iniţieze simultan procedura de icircnchidere a conexiunii Icircn acest caz ambele părţi vor trimite
FIN şi vor aştepta primirea unui ACK Icircn continuare fiecare va primi cererea de terminare şi va
trimite ACK Se observă că numărul de segmente transferate pentru realizarea icircnchiderii
conexiunii (4 segmente) este acelaşi ca la terminarea normală
3 Resetarea conexiunii
Există situaţii icircn care TCP doreşte resetarea conexiunii De exemplu dacă se solicită iniţierea
unei conexiuni la un port inexistent Icircn acest caz cealaltă parte va trimite un segment cu bitul
RST setat pentru a anula solicitarea O altă situaţie este atunci cacircnd se constată că celalalt capăt
al conexiunii nu răspunde un anumit timp (timeout)
Diagrama de stări
Toate evenimentele ce au loc icircn timpul stabilirii conexiunii transferului şi icircnchiderii conexiunii
pot fi rezumate printr-un automat finit cunoscut sub numele de diagrama de stări După cum
chiar numele sugerează este o maşină cu un număr limitat de stări O stare este păstrată pacircnă icircn
momentul apariţiei unui eveniment moment icircn care se poate trece icircn altă stare şisau efectua o
acţiune
Aceste stări posibile sunt (denumirile sunt asemănătoare cu cele utilizate de netstat) cele din
tabelul 71
Tabela Stările diagramei de stări TCP
Stare Descriere
CLOSED Nu există conexiune
LISTEN Serverul aşteaptă cereri de la clienţi
SYN_SENT Cerere de iniţiere (activă) a conexiunii Se
aşteaptă confirmarea
SYN_RCVD S-a primit o cerere de iniţiere conexiune
ESTABLISHED S-a stabilit conexiunea
FIN_WAIT_1 Aplicaţia a solicitat icircnchiderea conexiunii
FIN_WAIT_2 Serverul a acceptat icircnchiderea conexiunii
CLOSING Ambele părţi solicită simultan icircnchiderea
conexiunii
TIME_WAIT Conexiune icircnchisă dar se aşteaptă ca
pachetele retransmise să dispară
CLOSE_WAIT Serverul aşteaptă icircnchiderea dinspre partea
aplicaţiei
LAST_ACK Serverul a icircnchis conexiunea Aşteaptă
ultima confirmare
Icircn diagrama ilustrată icircn figura 74 putem observa 3 tipuri de tranziţii icircntre cele 11 stări tranziţii
ce corespund unei funcţionări normale pentru client (linii normale continue) pentru server (linii
normale icircntrerupte) şi tranziţii pentru situaţii nestandard (linii subţiri continue)
O comportarea normală pentru client presupune parcurgerea următoarelor stări CLOSED
SYN_SEND ESTABLISHED FIN_WAY_1 FIN_WAY_2 TIME_WAIT
Iniţial clientul TCP se află icircn starea CLOSED
Aşteptacircnd icircn starea CLOSED clientul poate primi de la aplicaţie o cerere de iniţiere
activă a unei conexiuni Trimite un segment SYN şi trece icircn starea SYN_SENT
Icircn starea SYN_SENT clientul aşteaptă de la server un segment ACK+SYN după care
trimite un ACK şi trece icircn starea ESTABLISHED Din acest moment poate icircncepe
transferul efectiv de date Clientul va rămacircne icircn această stare cacirct timp are de trimisprimit
date
Aflat icircn această stare clientul TCP poate primi din partea aplicaţiei o cerere de icircnchidere a
conexiunii Icircn acest caz va trimit un segment FIN şi trece icircn starea FIN_WAIT_1
Icircn această stare clientul aşteaptă ACK din partea serverului După ce-l primeşte
conexiunea icircntr-un sens se va icircnchide şi clientul trece icircn starea FIN_WAIT_2
Starea FIN_WAIT_2 durează pacircnă cacircnd primeşte cererea de icircnchidere a conexiunii FIN
din partea serverului Trimite ACK şi va trece icircn starea TIME_WAIT
Icircn această stare se va porni un timer cu valoarea setată la dublul timpului de viaţă estimat
pentru un segment de lungime maximă MSL (Maximum Segment Lifetime) Acest timer
permite retransmiterea ACK-ului icircn cazul icircn care acesta se pierde (celălalt capăt va da
timeout şi va retransmite segmentul FIN) Icircn tot acest time cei doi sockeţi (de la client şi
server) nu vor putea fi reutilizaţi Totodată pachetele icircntacircrziate care sosesc icircn această
perioadă sunt ignorate După expirarea acestui timer clientul revine icircn starea iniţială
CLOSED
Din punctul de vedere al unui server o comportare standard parcurge următoarele stări
CLOSED LISTEN SYN_RCVD ESTABLISHED CLOSE_WAIT şi LAST_ACK
Iniţial serverul TCP se află icircn starea CLOSED
Icircn această stare poate primi de la aplicaţia server o cerere de iniţiere activă şi trece icircn
starea LISTEN
Aflat icircn starea LISTEN serverului TCP poate recepţiona un segment SYN de la un client
TCP Icircn acest caz va trimite ACK+SYN şi va trece icircn starea SYN_RCVD
Icircn această stare serverul aşteaptă primirea confirmării de la client moment icircn care
conexiunea e stabilită icircn ambele sensuri şi se poate icircncepe transferul de date (starea
ESTABLISHED)
Clientul TCP poate solicita icircnchiderea conexiunii trimiţacircnd un segment FIN către server
Icircn acest caz serverul TCP trimite confirmarea şi trece icircn starea CLOSE_WAIT
Icircn această stare serverul aşteaptă să primească din partea programului server icircnchiderea
conexiunii moment icircn care va trimite către client un segment FIN şi trece icircn starea
LAST_ACK
Serverul aşteaptă primirea ultimei confirmări de la client după care revine icircn starea
CLOSED
Atacirct serverul cacirct şi clientul TCP se pot afla icircn oricare din cele 11 stări ale diagramei
Figura Diagrama de stări pentru TCP
4 Controlul fluxului
Dacă icircncă de la icircnceput s-a reuşit stabilirea formatului unui pachet TCP şi a modulului icircn care
trebuie să se facă icircnchiderea şi deschiderea unei conexiuni nu acelaşi lucru se poate spune şi
despre modul icircn care ar trebui să se realizeze controlul fluxului Ţinacircnd seama icircnsă că din 1989
(de cacircnd datează RFC-ul 2581 cel despre care am menţionat că specifică icircn mod clar modul icircn
care trebuie să se comporte o implementare de TCP) TCP-ul a rămas neschimbat putem să icircl
considerăm un rezultat important al domeniului reţelor de calculatoare
Icircn cele ce urmează vom icircnţelege prin controlul fluxului totalitatea algoritmilor care permit
atingerea unei viteze de transfer punct-la-punct cacirct mai mare pentru toate conexiunile existente
Icircn principal aceşti algoritmi stabilesc modul icircn care segmentele şi confirmările trebuie trimise şi
ce acţiuni trebuie executate icircn situaţiile icircn care răspunsurile aşteptate de la celălalt capăt icircntacircrzie
să vină
Subsections
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
Icircntacircrzierea confirmărilor
O modalitate simplă de generare a confirmărilor este de a trimite cacircte una pentru fiecare segment
primit Această politică prezintă avantajul de a face comunicaţia self-clocking icircnsă este
ineficientă dacă segmentele care nu conţin decacirct confirmări sunt urmate la scurtă distanţă (cacircteva
zeci de milisecunde) de segmente ce conţin date efective Pentru a evita această situaţie se
procedează2 la icircntacircrzierea (200ms este o valoare uzuală icircn RFC 1122 se specifică o valoare
maximă de 500ms) a segmentelor care conţin doar confirmări Această strategie face posibil ca
un răspuns generat de primirea unor date să plece sper celălalt capăt icircn acelaşi segment cu
confirmarea
Observaţie deoarece este dificil de menţinut timere pentru fiecare confirmare diferenţa de
200ms este calculată de un timer global Din acest motiv modul efectiv de comportare poate fi
descris şi icircn felul următor cacircnd un segment nu conţine decacirct o confirmare el este pus icircntr-o
coadă ce va fi inspectată de un proces care din 200 icircn 200 ms trimite tot ce s-a acumulat icircn
coada
Footnotes
2
Acest comportament a fost propus de David D Clark icircn iulie 1982 icircn RFC 813
Algoritmul Nagle
Acest algoritm3 icircncearcă să icircmbunătăţească performanţele exploatacircnd următoarea caracteristică
foarte des icircntacirclnită icircn dialogul dintre două staţii dacă se icircncearcă trimiterea unor date de
dimensiune mică icircnsă există icircncă date neconfirmate de partener atunci ele sunt buffer-ate şi
trimise icircntr-un segment mai mare cacircnd soseşte confirmarea aşteptată Icircn acest fel se poate evita
generarea datagramelor mici (tinygrame) icircn situaţia unei legături lente Icircn cazul unei legături
rapide confirmările vor veni repede şi icircntacircrzierea introdusă de algoritm va neglijabilă
Există icircnsă şi cazuri icircn care acest algoritm duce la deprecierea performanţelor mesajele scurte
generate de mişcările mouse-ului icircn cazul folosirii unui server X Window sau utilizarea tastelor
care trimit mai mult de un caracter (secvenţe escape) Pentru a rezolva aceste inconveninte API-
ul de utilizare a TCP-ului trebuie să ofere o modalitate de a dezactiva acest algoritm (icircn sistemele
bazate pe sockeţi există icircn acest scop opţiunea TCP_NODELAY)
Footnotes
algoritm3
Algoritmul aparţinacircnd lui John Nagle a fost propus icircn ianuarie 1984 icircn RFC 896
Fereastra glisantă
Algoritmul implementat de TCP pentru a implementa transferul sigur de date este cunoscut icircn
teorie sub numele de Go-Back-N Icircn acest algoritm se utilizează numere de secvenţă pentru a
distinge pachetele icircntre ele şi o coadă (dimensiunea maximă a cozii reprezintă fereastra) de
pachetele a căror confirmare se aşteaptă Pachetele se icircmpart icircn 4 categorii
1 pachete trimis şi pentru care s-a primit confirmare
2 pachete trimise şi pentru care se aşteaptă icircncă confirmarea
3 pachete care nu au fost trimise icircncă dar care nu depăşesc limitele ferestrei şi deci pot fi
trimise
4 pachete care icircncă nu au fost trimite şi care nici nu vor putea fi trimise decacirct după ce au
fost trimise toate pachetele din categoria 3 şi s-au primit o parte din confirmările la
pachetele din categoria 2
Dacă confirmările pentru pachetele din categoria 2 icircntacircrzie prea mult (un mecanism de timer-e
informează asupra acestui lucru) atunci ele vor fi retrimise Icircn versiunea iniţială TCP-ul nu
permitea decacirct confirmări pozitive ceea ce icircnseamnă că avansarea ferestrei se va icircmpotmoli la
segmentele neconfirmate Cum se poate evita aceasta situaţie vom discuta icircn detaliu icircn capitolele
următoare O soluţie foarte radicală o constituie introducerea de confirmări selective (acest lucru
este realizat de RFC 2018 din octombrie 1996) Această modifică face ca TCP-ul actual să fie un
hibrid de Go-Back-N şi Selective Repeat
Deoarece dimensiunea ferestrei este anunţată la fiecare segment un client lent poate ca pe măsură
ce trimite confirmările să informeze despre progresul icircnregistrat la livrarea datelor următorului
nivel (aplicaţie) Dacă datele vin prea repede pentru viteza cu care clientul procesează datele
fereastra fereastra se va dimiua şi chiar icircnchide (acest lucru se realizează anunţacircnd o fereastră de
dimensiune zero) Cum se realizează efectiv redeschiderea vom analiza icircntr-un capitol viitor
Slow start
Un transfer de date TCP poate să icircnceapă prin transmiterea de segmente pacircnă la umplerea
icircntregii ferestre după care fie se primesc confirmări care vor permite unor noi pachete să fie
trimise fie vor expira timer-ele de retransmisie şi se va icircncepe retrimiterea pachetelor de la
icircnceputul ferestrei Din păcate un astfel de comportament poate duce la pomparea icircn reţea a unui
număr de pachete prea mare pentru capacitatea disponibilă efectiv icircnrăutăţind congestia Pentru
a evita acest lucru s-a propus următoarea soluţie4 iniţial se trimite un segment după primirea
confirmării lui se trimit două segmente după sosirea confirmărilor pentru ele se trimit patru
segmente şi aşa mai departe La un moment dat fie vor icircncepe să se piardă segmente (un indiciu
că s-a atins capacitatea maximă a canalului) fie se va umple fereastra pe care o anunţă cel care
primeşte Trebuie să remarcam că datorită creşterii exponenţiale a numărului de segmente se va
atinge destul de repede una din cele două situaţii
Modalitatea efectivă de implementare a acestui algoritm are la bază utilizarea unei ferestre de
congestie (congestion window cwnd) care este iniţializată cu dimensiunea unui segment (cwnd
se calculează icircn octeţi) şi la fiecare pas este dublată fereastra efectivă din cadrul căreia se pot
trimite segmente este dată de minimul dintre ultima fereastra comunicată de partener şi cwnd
Footnotes
soluţie4
Soluţia aparţine lui V Jacobson şi a fost prezentată icircn 1988 la conferinţă ACM
SIGCOMM-88
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Deoarece TCP trebuie să funcţioneze icircn condiţii variate de latenţă modul icircn care se face
retransmiterea trebuie să fie cacirct mai flexibil (şi simplu icircn acelaşi timp pentru a introduce un
overhead cacirct mai mic) Timpul cacirct se aşteaptă venirea unei confirmări (retransmission timeout
RTO) este calculat prin cronometrarea timpului care icirci ia unui segment trimis să fie confirmat
Pentru o anumită conexiune se cronometrează cacircte un singur segment la un moment dat iar pe
baza RTT-ului măsurat se actualizează valoare RTO-ului
Icircn RFC 793 formula de calcul a RTO-ului este următoarea
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
dacă la destinaţie au ajuns octeţii 1-1024 şi următorul segment primit conţine octeţii
2049-3072 nu se poate trimite confirmare pentru cel de-al doilea segment deci
confirmarea va cuprinde numărul de secvenţă 1025
lungimea antetului - 4 biţi
Specifică dimensiunea antetului ca număr de cuvinte de 32 de biţi (4 octeţi) Antetul
poate avea icircntre 20 şi 60 de octeţi deci valoarea acestui cacircmp va fi icircntre 5 (5 x 4 = 20
octeţi) şi 15 (15 x 4 = 60)
6 biţi rezervaţi pentru utilizări viitoare
6 biţi de control reprezentacircnd următoarele flag-uri ce pot fi setate simultan
o URG - cacircmpul urgent pointer este valid
o ACK - cacircmpul de confirmare este valid
o PSH - destinaţia trebuie să trimită datele către nivelul aplicaţie cacirct mai devreme
o RST - se doreşte resetarea conexiunii
o SYN - iniţierea conexiunii
o FIN - icircnchiderea conexiunii
dimensiunea ferestrei - 16 biţi
Reprezintă numărul de octeţi (icircncepacircnd cu numărul de secvenţă conţinut icircn cacircmpul de
confirmare) pe care destinaţia e dispusă să-l primească Este limitat la 65535 octeţi dar
cu toate că pare o limită destul de mare există situaţii cacircnd se doresc valori mult mai
mari Icircn acest scop se folosesc nişte opţiuni speciale descrise ceva mai tacircrziu care permit
scalarea ferestrei
suma de control - 16 biţi
Această sumă de control acoperă icircntregul segment TCP (atacirct datele cacirct şi antetul TCP) şi
spre deosebire de UDP este obligatoriu să fie completat de transmiţător şi verificat de
receptor Dar ca şi icircn cazul UDP-ului la calculul sumei de control se ia in considerare şi
o zona specială de 12 octeţi ce cuprinde pentru re-verificare cacircmpuri din antetul IP
(adresa IP a sursei şi a destinaţiei)[aici tre sa vina o referire la poza cu pseudo-antetu]
După adăugarea acestui pseudo-antet datele se icircmpart icircn cuvinte de 16 biţi icircn vederea
calculării sumei de control adăugacircndu-se eventual şi un octet de aliniere
urgent pointer - 16 biţi
Este utilizat pentru specificarea deplasamentului ultimului octet de date trimis icircn regim
urgent Astfel ultimul octet din secvenţa urgentă se obţine adunacircnd acest cacircmp la
numărul de secvenţă Ce icircnseamnă acest mod urgent de transmitere există situaţii icircn care
aplicaţiile vor să trimită date `neordonate` Să presupunem că aplicaţia a trimis către
nivelul transport o cantitate mare de date dar la un moment dat observă ceva icircn neregulă
şi doreşte să anuleze operaţia Dacă trimite o comandă de anulare aceasta va fi adăugată
la sfacircrşitul şirului de octeţi deci nu se va putea icircmpiedica ajungerea acestora la nivelul
aplicaţie de la receptor Activacircnd modul urgent datele urgente (comanda de anulare) vor
fi plasate la icircnceputul pachetului Aplicaţiile mai cunoscute care folosesc acest mod sunt
Telnet Rlogin şi FTP
opţiuni - pacircnă la 40 de octeţi (figura 73)
Cele mai utilizate opţiuni sunt
o Sfacircrşit de opţiuni (end of option) - 1 octet
Este utilizat pentru alinierea datelor conţinute icircn cacircmpul de opţiuni Nu poate fi
utilizat decacirct o singură dată marcacircndu-se astfel sfacircrşitul opţiunilor şi icircnceperea
datelor efective Dacă pentru alinierea la un cuvacircnt de 32 de biţi e nevoie de mai
mult de 1 byte se va utiliza opţiunea no operation Orice apare după această
opţiune pacircnă la icircnceputul cuvacircntului următor de 32 de biţi e ignorat
o no operation - 1 octet
Utilizat pentru alinierea la cuvinte de 32 de biţi
o Dimensiunea maximă a segmentului (Maximum Segment Size (MSS)) - 16 biţi
Icircn ciuda denumirii defineşte lungimea maximă a datelor nu dimensiunea
icircntregului segment Poate lua valori icircntre 0 şi 65535 valoarea implicită fiind 536
Această opţiune e valabilă doar icircn pachetele de iniţiere a conexiunii (cele cu flag-
ul SYN setat) fiecare parte făcacircnd cunoscută dimensiunea maximă a datelor
dispusă să le primească icircntr-un pachet Icircn principiu cu cacirct această valoarea e mai
mare e mai bine (deoarece se recuperează din spaţiul ocupat de antetele TCP şi
IP) pacircnă cacircnd apare fragmentarea Valoarea maximă la care se poate seta este
MTU (Maximum Transfer Unit) minus dimensiunea antetului IP şi TCP (1460
octeţi icircn cazul Ethernet)
o Factor de scalare a ferestrei (Window scale factor) - 1 octet
Pentru situaţiile icircn care se doreşte utilizarea unei ferestre mai mare de 65535 bytes
se poate utiliza acest cacircmp pentru mărirea dimensiunii ferestrei Noua dimensiune
va fi Chiar dacă
factorul de scalare poate fi maxim 255 icircn cazul TCPIP el nu poate depăşi
valoarea 16 deoarece dimensiunea maximă a ferestrei nu poate fi mai mare decacirct
valoarea celui mai mare număr de secvenţă ( )
Acest factor se poate seta doar la iniţierea conexiunii Icircn timpul transferului de
date se poate modifica dimensiunea ferestrei dar factorul de scalare rămacircne
acelaşi Dacă cel care a iniţiat conexiunea a trimis icircn segmentul de iniţiere şi acest
factor dar icircn pachetul cu ACK destinatarul nu şi-a trimis şi el factorul atunci se la
considera 0 icircn ambele direcţii Invers dacă cel care solicită deschiderea
conexiunii nu setează factorul destinaţia nu va putea seta factorul de scalare
o Timestamp - 10 octeţi
Utilizat pentru reţinerea timpului icircn vederea calculării RTT (Round Trip Time)
Cacircmpul timestamp e completat de sursă icircn momentul trimiterii segmentului La
destinaţie valoarea este reţinută şi copiată icircn cacircmpul timestamp echo reply al
pachetului cu confirmarea RTT-ul este calculat de sursă făcacircnd diferenţa dintre
timpul curent şi această valoare
Figura Opţiuni TCP
3 Iniţierea şi terminarea unei conexiuni TCP
TCP este un protocol orientat conexiune deci presupune stabilirea unei căi virtuale icircntre sursă şi
destinaţie
Subsections
Protocolul de iniţiere
o 1 Deschiderea simultană
Protocolul de terminare
o 2 Terminarea simultană
o 3 Resetarea conexiunii
Diagrama de stări
Protocolul de iniţiere
Modul de transmisie icircn cazul protocolului TCP este full-duplex deci sunt transmise date
simultan icircn ambele direcţii Aceasta presupune că cel care iniţiază conexiunea trebuie să
primească aprobarea celuilalt capăt icircnainte de icircnceperea transferului de date sursa icircşi anunţă
intenţia de a iniţia o conexiune destinaţia trimite un pachet cu confirmarea cererii şi un pachet de
iniţiere a conexiunii de la el la sursă iar apoi sursa confirmă cererea primită de la destinaţie Paşii
2 şi 3 pot fi realizaţi prin trimiterea unui singur pachet de aceea protocolul de iniţiere este
cunoscut sub numele de three-way handshake
Icircn cadrul protocolului de iniţiere există 2 tipuri de cereri de iniţiere cerere activă (active open)
iniţiată de clientul ce doreşte să stabilească conexiunea cu serverul şi cerere pasivă (passive
open) din partea serverului
Cei 3 paşi sunt
1 Clientul trimite un segment cu flag-ul SYN setat şi care conţine portul sursă portul de la
destinaţie şi numărul de secvenţă generat iniţial (ISN) de la care se vor numerota octeţii
de la client către server Opţional se pot stabili parametrii conexiunii prin setarea lungimii
maxime a segmentelor (MSS) dispus să le primească de la server factorului de scalare a
ferestrei Acest prim segment nu conţine nici un parametru de confirmare şi de asemenea
nu are rost să conţine să seteze dimensiunea ferestrei
2 Al doilea segment e trimis de server şi are un rol dublu confirmă segmentul primit de la
client prin setarea flag-ului ACK şi completează numărul de secvenţă cu numărul de
secvenţă primit plus 1 şi al doilea rol iniţializează conexiunea de la el către client prin
setarea flag-ului SYN şi generarea unui număr de secvenţă iniţial ce va fi folosit icircn
numerotarea octeţilor de la server spre client Pe lacircngă aceasta trebuie să conţină
dimensiunea ferestrei şi opţional poate seta factorul de scalare şi dimensiunea maximă a
segmentului acceptat
3 Clientul trimite un segment cu confirmarea cererii din partea serverului (ACK setat +
completează numărul confirmat cu numărul de secvenţa primit + 1) Ca şi icircn cazul
pasului 2 trebuie să seteze dimensiunea ferestrei Acest pachet poate conţine date
Subsections
1 Deschiderea simultană
1 Deschiderea simultană
Se poate icircntacircmpla ca uneori cele două capete care vor să comunice să icircncerce să stabilească
conexiunea simultan Icircn acest caz după ce fiecare a trimis segmentul de iniţiere (iniţiere activă)
ambele vor trimite un segment cu SYN + ACK şi se va stabili o singură conexiune nu două
Protocolul de terminare
Oricare dintre cele două părţi poate solicita icircnchiderea conexiunii dar conexiunea fiind full-
duplex transferul de date icircn celălalt sens poate continua (această situaţie e denumită half-close)
O icircnchidere completă a unei conexiuni TCP presupune următorii paşi
1 Clientul trimite un segment cu flag-ul FIN activat solicitacircnd icircnchiderea conexiunii
2 Serverul trimite un segment ACK confirmacircnd primirea cererea Numărul de confirmare
se completează normal ca numărul de secvenţă primit + 1
3 Serverul continuă să trimită date către client şi cacircnd doreşte să icircnchidă şi el conexiunea
trimite un segment cu FIN activat
4 Clientul trimite un pachet ACK confirmacircnd icircnchiderea conexiunii
Cel care iniţiază primul procedura de icircnchidere (trimite primul FIN) realizează o icircnchidere activă
(active close) iar celălalt capăt o icircnchidere pasivă (passive close) Icircn mod normal cel care
realizează iniţierea activă va fi primul ce va trimite FIN dar oricare dintre cei doi poate icircnchide
activ conexiunea
Subsections
2 Terminarea simultană
3 Resetarea conexiunii
2 Terminarea simultană
Icircn mod similar cu deschiderea simultană există posibilitatea ca ambele capete ale conexiunii TCP
să iniţieze simultan procedura de icircnchidere a conexiunii Icircn acest caz ambele părţi vor trimite
FIN şi vor aştepta primirea unui ACK Icircn continuare fiecare va primi cererea de terminare şi va
trimite ACK Se observă că numărul de segmente transferate pentru realizarea icircnchiderii
conexiunii (4 segmente) este acelaşi ca la terminarea normală
3 Resetarea conexiunii
Există situaţii icircn care TCP doreşte resetarea conexiunii De exemplu dacă se solicită iniţierea
unei conexiuni la un port inexistent Icircn acest caz cealaltă parte va trimite un segment cu bitul
RST setat pentru a anula solicitarea O altă situaţie este atunci cacircnd se constată că celalalt capăt
al conexiunii nu răspunde un anumit timp (timeout)
Diagrama de stări
Toate evenimentele ce au loc icircn timpul stabilirii conexiunii transferului şi icircnchiderii conexiunii
pot fi rezumate printr-un automat finit cunoscut sub numele de diagrama de stări După cum
chiar numele sugerează este o maşină cu un număr limitat de stări O stare este păstrată pacircnă icircn
momentul apariţiei unui eveniment moment icircn care se poate trece icircn altă stare şisau efectua o
acţiune
Aceste stări posibile sunt (denumirile sunt asemănătoare cu cele utilizate de netstat) cele din
tabelul 71
Tabela Stările diagramei de stări TCP
Stare Descriere
CLOSED Nu există conexiune
LISTEN Serverul aşteaptă cereri de la clienţi
SYN_SENT Cerere de iniţiere (activă) a conexiunii Se
aşteaptă confirmarea
SYN_RCVD S-a primit o cerere de iniţiere conexiune
ESTABLISHED S-a stabilit conexiunea
FIN_WAIT_1 Aplicaţia a solicitat icircnchiderea conexiunii
FIN_WAIT_2 Serverul a acceptat icircnchiderea conexiunii
CLOSING Ambele părţi solicită simultan icircnchiderea
conexiunii
TIME_WAIT Conexiune icircnchisă dar se aşteaptă ca
pachetele retransmise să dispară
CLOSE_WAIT Serverul aşteaptă icircnchiderea dinspre partea
aplicaţiei
LAST_ACK Serverul a icircnchis conexiunea Aşteaptă
ultima confirmare
Icircn diagrama ilustrată icircn figura 74 putem observa 3 tipuri de tranziţii icircntre cele 11 stări tranziţii
ce corespund unei funcţionări normale pentru client (linii normale continue) pentru server (linii
normale icircntrerupte) şi tranziţii pentru situaţii nestandard (linii subţiri continue)
O comportarea normală pentru client presupune parcurgerea următoarelor stări CLOSED
SYN_SEND ESTABLISHED FIN_WAY_1 FIN_WAY_2 TIME_WAIT
Iniţial clientul TCP se află icircn starea CLOSED
Aşteptacircnd icircn starea CLOSED clientul poate primi de la aplicaţie o cerere de iniţiere
activă a unei conexiuni Trimite un segment SYN şi trece icircn starea SYN_SENT
Icircn starea SYN_SENT clientul aşteaptă de la server un segment ACK+SYN după care
trimite un ACK şi trece icircn starea ESTABLISHED Din acest moment poate icircncepe
transferul efectiv de date Clientul va rămacircne icircn această stare cacirct timp are de trimisprimit
date
Aflat icircn această stare clientul TCP poate primi din partea aplicaţiei o cerere de icircnchidere a
conexiunii Icircn acest caz va trimit un segment FIN şi trece icircn starea FIN_WAIT_1
Icircn această stare clientul aşteaptă ACK din partea serverului După ce-l primeşte
conexiunea icircntr-un sens se va icircnchide şi clientul trece icircn starea FIN_WAIT_2
Starea FIN_WAIT_2 durează pacircnă cacircnd primeşte cererea de icircnchidere a conexiunii FIN
din partea serverului Trimite ACK şi va trece icircn starea TIME_WAIT
Icircn această stare se va porni un timer cu valoarea setată la dublul timpului de viaţă estimat
pentru un segment de lungime maximă MSL (Maximum Segment Lifetime) Acest timer
permite retransmiterea ACK-ului icircn cazul icircn care acesta se pierde (celălalt capăt va da
timeout şi va retransmite segmentul FIN) Icircn tot acest time cei doi sockeţi (de la client şi
server) nu vor putea fi reutilizaţi Totodată pachetele icircntacircrziate care sosesc icircn această
perioadă sunt ignorate După expirarea acestui timer clientul revine icircn starea iniţială
CLOSED
Din punctul de vedere al unui server o comportare standard parcurge următoarele stări
CLOSED LISTEN SYN_RCVD ESTABLISHED CLOSE_WAIT şi LAST_ACK
Iniţial serverul TCP se află icircn starea CLOSED
Icircn această stare poate primi de la aplicaţia server o cerere de iniţiere activă şi trece icircn
starea LISTEN
Aflat icircn starea LISTEN serverului TCP poate recepţiona un segment SYN de la un client
TCP Icircn acest caz va trimite ACK+SYN şi va trece icircn starea SYN_RCVD
Icircn această stare serverul aşteaptă primirea confirmării de la client moment icircn care
conexiunea e stabilită icircn ambele sensuri şi se poate icircncepe transferul de date (starea
ESTABLISHED)
Clientul TCP poate solicita icircnchiderea conexiunii trimiţacircnd un segment FIN către server
Icircn acest caz serverul TCP trimite confirmarea şi trece icircn starea CLOSE_WAIT
Icircn această stare serverul aşteaptă să primească din partea programului server icircnchiderea
conexiunii moment icircn care va trimite către client un segment FIN şi trece icircn starea
LAST_ACK
Serverul aşteaptă primirea ultimei confirmări de la client după care revine icircn starea
CLOSED
Atacirct serverul cacirct şi clientul TCP se pot afla icircn oricare din cele 11 stări ale diagramei
Figura Diagrama de stări pentru TCP
4 Controlul fluxului
Dacă icircncă de la icircnceput s-a reuşit stabilirea formatului unui pachet TCP şi a modulului icircn care
trebuie să se facă icircnchiderea şi deschiderea unei conexiuni nu acelaşi lucru se poate spune şi
despre modul icircn care ar trebui să se realizeze controlul fluxului Ţinacircnd seama icircnsă că din 1989
(de cacircnd datează RFC-ul 2581 cel despre care am menţionat că specifică icircn mod clar modul icircn
care trebuie să se comporte o implementare de TCP) TCP-ul a rămas neschimbat putem să icircl
considerăm un rezultat important al domeniului reţelor de calculatoare
Icircn cele ce urmează vom icircnţelege prin controlul fluxului totalitatea algoritmilor care permit
atingerea unei viteze de transfer punct-la-punct cacirct mai mare pentru toate conexiunile existente
Icircn principal aceşti algoritmi stabilesc modul icircn care segmentele şi confirmările trebuie trimise şi
ce acţiuni trebuie executate icircn situaţiile icircn care răspunsurile aşteptate de la celălalt capăt icircntacircrzie
să vină
Subsections
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
Icircntacircrzierea confirmărilor
O modalitate simplă de generare a confirmărilor este de a trimite cacircte una pentru fiecare segment
primit Această politică prezintă avantajul de a face comunicaţia self-clocking icircnsă este
ineficientă dacă segmentele care nu conţin decacirct confirmări sunt urmate la scurtă distanţă (cacircteva
zeci de milisecunde) de segmente ce conţin date efective Pentru a evita această situaţie se
procedează2 la icircntacircrzierea (200ms este o valoare uzuală icircn RFC 1122 se specifică o valoare
maximă de 500ms) a segmentelor care conţin doar confirmări Această strategie face posibil ca
un răspuns generat de primirea unor date să plece sper celălalt capăt icircn acelaşi segment cu
confirmarea
Observaţie deoarece este dificil de menţinut timere pentru fiecare confirmare diferenţa de
200ms este calculată de un timer global Din acest motiv modul efectiv de comportare poate fi
descris şi icircn felul următor cacircnd un segment nu conţine decacirct o confirmare el este pus icircntr-o
coadă ce va fi inspectată de un proces care din 200 icircn 200 ms trimite tot ce s-a acumulat icircn
coada
Footnotes
2
Acest comportament a fost propus de David D Clark icircn iulie 1982 icircn RFC 813
Algoritmul Nagle
Acest algoritm3 icircncearcă să icircmbunătăţească performanţele exploatacircnd următoarea caracteristică
foarte des icircntacirclnită icircn dialogul dintre două staţii dacă se icircncearcă trimiterea unor date de
dimensiune mică icircnsă există icircncă date neconfirmate de partener atunci ele sunt buffer-ate şi
trimise icircntr-un segment mai mare cacircnd soseşte confirmarea aşteptată Icircn acest fel se poate evita
generarea datagramelor mici (tinygrame) icircn situaţia unei legături lente Icircn cazul unei legături
rapide confirmările vor veni repede şi icircntacircrzierea introdusă de algoritm va neglijabilă
Există icircnsă şi cazuri icircn care acest algoritm duce la deprecierea performanţelor mesajele scurte
generate de mişcările mouse-ului icircn cazul folosirii unui server X Window sau utilizarea tastelor
care trimit mai mult de un caracter (secvenţe escape) Pentru a rezolva aceste inconveninte API-
ul de utilizare a TCP-ului trebuie să ofere o modalitate de a dezactiva acest algoritm (icircn sistemele
bazate pe sockeţi există icircn acest scop opţiunea TCP_NODELAY)
Footnotes
algoritm3
Algoritmul aparţinacircnd lui John Nagle a fost propus icircn ianuarie 1984 icircn RFC 896
Fereastra glisantă
Algoritmul implementat de TCP pentru a implementa transferul sigur de date este cunoscut icircn
teorie sub numele de Go-Back-N Icircn acest algoritm se utilizează numere de secvenţă pentru a
distinge pachetele icircntre ele şi o coadă (dimensiunea maximă a cozii reprezintă fereastra) de
pachetele a căror confirmare se aşteaptă Pachetele se icircmpart icircn 4 categorii
1 pachete trimis şi pentru care s-a primit confirmare
2 pachete trimise şi pentru care se aşteaptă icircncă confirmarea
3 pachete care nu au fost trimise icircncă dar care nu depăşesc limitele ferestrei şi deci pot fi
trimise
4 pachete care icircncă nu au fost trimite şi care nici nu vor putea fi trimise decacirct după ce au
fost trimise toate pachetele din categoria 3 şi s-au primit o parte din confirmările la
pachetele din categoria 2
Dacă confirmările pentru pachetele din categoria 2 icircntacircrzie prea mult (un mecanism de timer-e
informează asupra acestui lucru) atunci ele vor fi retrimise Icircn versiunea iniţială TCP-ul nu
permitea decacirct confirmări pozitive ceea ce icircnseamnă că avansarea ferestrei se va icircmpotmoli la
segmentele neconfirmate Cum se poate evita aceasta situaţie vom discuta icircn detaliu icircn capitolele
următoare O soluţie foarte radicală o constituie introducerea de confirmări selective (acest lucru
este realizat de RFC 2018 din octombrie 1996) Această modifică face ca TCP-ul actual să fie un
hibrid de Go-Back-N şi Selective Repeat
Deoarece dimensiunea ferestrei este anunţată la fiecare segment un client lent poate ca pe măsură
ce trimite confirmările să informeze despre progresul icircnregistrat la livrarea datelor următorului
nivel (aplicaţie) Dacă datele vin prea repede pentru viteza cu care clientul procesează datele
fereastra fereastra se va dimiua şi chiar icircnchide (acest lucru se realizează anunţacircnd o fereastră de
dimensiune zero) Cum se realizează efectiv redeschiderea vom analiza icircntr-un capitol viitor
Slow start
Un transfer de date TCP poate să icircnceapă prin transmiterea de segmente pacircnă la umplerea
icircntregii ferestre după care fie se primesc confirmări care vor permite unor noi pachete să fie
trimise fie vor expira timer-ele de retransmisie şi se va icircncepe retrimiterea pachetelor de la
icircnceputul ferestrei Din păcate un astfel de comportament poate duce la pomparea icircn reţea a unui
număr de pachete prea mare pentru capacitatea disponibilă efectiv icircnrăutăţind congestia Pentru
a evita acest lucru s-a propus următoarea soluţie4 iniţial se trimite un segment după primirea
confirmării lui se trimit două segmente după sosirea confirmărilor pentru ele se trimit patru
segmente şi aşa mai departe La un moment dat fie vor icircncepe să se piardă segmente (un indiciu
că s-a atins capacitatea maximă a canalului) fie se va umple fereastra pe care o anunţă cel care
primeşte Trebuie să remarcam că datorită creşterii exponenţiale a numărului de segmente se va
atinge destul de repede una din cele două situaţii
Modalitatea efectivă de implementare a acestui algoritm are la bază utilizarea unei ferestre de
congestie (congestion window cwnd) care este iniţializată cu dimensiunea unui segment (cwnd
se calculează icircn octeţi) şi la fiecare pas este dublată fereastra efectivă din cadrul căreia se pot
trimite segmente este dată de minimul dintre ultima fereastra comunicată de partener şi cwnd
Footnotes
soluţie4
Soluţia aparţine lui V Jacobson şi a fost prezentată icircn 1988 la conferinţă ACM
SIGCOMM-88
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Deoarece TCP trebuie să funcţioneze icircn condiţii variate de latenţă modul icircn care se face
retransmiterea trebuie să fie cacirct mai flexibil (şi simplu icircn acelaşi timp pentru a introduce un
overhead cacirct mai mic) Timpul cacirct se aşteaptă venirea unei confirmări (retransmission timeout
RTO) este calculat prin cronometrarea timpului care icirci ia unui segment trimis să fie confirmat
Pentru o anumită conexiune se cronometrează cacircte un singur segment la un moment dat iar pe
baza RTT-ului măsurat se actualizează valoare RTO-ului
Icircn RFC 793 formula de calcul a RTO-ului este următoarea
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
o Sfacircrşit de opţiuni (end of option) - 1 octet
Este utilizat pentru alinierea datelor conţinute icircn cacircmpul de opţiuni Nu poate fi
utilizat decacirct o singură dată marcacircndu-se astfel sfacircrşitul opţiunilor şi icircnceperea
datelor efective Dacă pentru alinierea la un cuvacircnt de 32 de biţi e nevoie de mai
mult de 1 byte se va utiliza opţiunea no operation Orice apare după această
opţiune pacircnă la icircnceputul cuvacircntului următor de 32 de biţi e ignorat
o no operation - 1 octet
Utilizat pentru alinierea la cuvinte de 32 de biţi
o Dimensiunea maximă a segmentului (Maximum Segment Size (MSS)) - 16 biţi
Icircn ciuda denumirii defineşte lungimea maximă a datelor nu dimensiunea
icircntregului segment Poate lua valori icircntre 0 şi 65535 valoarea implicită fiind 536
Această opţiune e valabilă doar icircn pachetele de iniţiere a conexiunii (cele cu flag-
ul SYN setat) fiecare parte făcacircnd cunoscută dimensiunea maximă a datelor
dispusă să le primească icircntr-un pachet Icircn principiu cu cacirct această valoarea e mai
mare e mai bine (deoarece se recuperează din spaţiul ocupat de antetele TCP şi
IP) pacircnă cacircnd apare fragmentarea Valoarea maximă la care se poate seta este
MTU (Maximum Transfer Unit) minus dimensiunea antetului IP şi TCP (1460
octeţi icircn cazul Ethernet)
o Factor de scalare a ferestrei (Window scale factor) - 1 octet
Pentru situaţiile icircn care se doreşte utilizarea unei ferestre mai mare de 65535 bytes
se poate utiliza acest cacircmp pentru mărirea dimensiunii ferestrei Noua dimensiune
va fi Chiar dacă
factorul de scalare poate fi maxim 255 icircn cazul TCPIP el nu poate depăşi
valoarea 16 deoarece dimensiunea maximă a ferestrei nu poate fi mai mare decacirct
valoarea celui mai mare număr de secvenţă ( )
Acest factor se poate seta doar la iniţierea conexiunii Icircn timpul transferului de
date se poate modifica dimensiunea ferestrei dar factorul de scalare rămacircne
acelaşi Dacă cel care a iniţiat conexiunea a trimis icircn segmentul de iniţiere şi acest
factor dar icircn pachetul cu ACK destinatarul nu şi-a trimis şi el factorul atunci se la
considera 0 icircn ambele direcţii Invers dacă cel care solicită deschiderea
conexiunii nu setează factorul destinaţia nu va putea seta factorul de scalare
o Timestamp - 10 octeţi
Utilizat pentru reţinerea timpului icircn vederea calculării RTT (Round Trip Time)
Cacircmpul timestamp e completat de sursă icircn momentul trimiterii segmentului La
destinaţie valoarea este reţinută şi copiată icircn cacircmpul timestamp echo reply al
pachetului cu confirmarea RTT-ul este calculat de sursă făcacircnd diferenţa dintre
timpul curent şi această valoare
Figura Opţiuni TCP
3 Iniţierea şi terminarea unei conexiuni TCP
TCP este un protocol orientat conexiune deci presupune stabilirea unei căi virtuale icircntre sursă şi
destinaţie
Subsections
Protocolul de iniţiere
o 1 Deschiderea simultană
Protocolul de terminare
o 2 Terminarea simultană
o 3 Resetarea conexiunii
Diagrama de stări
Protocolul de iniţiere
Modul de transmisie icircn cazul protocolului TCP este full-duplex deci sunt transmise date
simultan icircn ambele direcţii Aceasta presupune că cel care iniţiază conexiunea trebuie să
primească aprobarea celuilalt capăt icircnainte de icircnceperea transferului de date sursa icircşi anunţă
intenţia de a iniţia o conexiune destinaţia trimite un pachet cu confirmarea cererii şi un pachet de
iniţiere a conexiunii de la el la sursă iar apoi sursa confirmă cererea primită de la destinaţie Paşii
2 şi 3 pot fi realizaţi prin trimiterea unui singur pachet de aceea protocolul de iniţiere este
cunoscut sub numele de three-way handshake
Icircn cadrul protocolului de iniţiere există 2 tipuri de cereri de iniţiere cerere activă (active open)
iniţiată de clientul ce doreşte să stabilească conexiunea cu serverul şi cerere pasivă (passive
open) din partea serverului
Cei 3 paşi sunt
1 Clientul trimite un segment cu flag-ul SYN setat şi care conţine portul sursă portul de la
destinaţie şi numărul de secvenţă generat iniţial (ISN) de la care se vor numerota octeţii
de la client către server Opţional se pot stabili parametrii conexiunii prin setarea lungimii
maxime a segmentelor (MSS) dispus să le primească de la server factorului de scalare a
ferestrei Acest prim segment nu conţine nici un parametru de confirmare şi de asemenea
nu are rost să conţine să seteze dimensiunea ferestrei
2 Al doilea segment e trimis de server şi are un rol dublu confirmă segmentul primit de la
client prin setarea flag-ului ACK şi completează numărul de secvenţă cu numărul de
secvenţă primit plus 1 şi al doilea rol iniţializează conexiunea de la el către client prin
setarea flag-ului SYN şi generarea unui număr de secvenţă iniţial ce va fi folosit icircn
numerotarea octeţilor de la server spre client Pe lacircngă aceasta trebuie să conţină
dimensiunea ferestrei şi opţional poate seta factorul de scalare şi dimensiunea maximă a
segmentului acceptat
3 Clientul trimite un segment cu confirmarea cererii din partea serverului (ACK setat +
completează numărul confirmat cu numărul de secvenţa primit + 1) Ca şi icircn cazul
pasului 2 trebuie să seteze dimensiunea ferestrei Acest pachet poate conţine date
Subsections
1 Deschiderea simultană
1 Deschiderea simultană
Se poate icircntacircmpla ca uneori cele două capete care vor să comunice să icircncerce să stabilească
conexiunea simultan Icircn acest caz după ce fiecare a trimis segmentul de iniţiere (iniţiere activă)
ambele vor trimite un segment cu SYN + ACK şi se va stabili o singură conexiune nu două
Protocolul de terminare
Oricare dintre cele două părţi poate solicita icircnchiderea conexiunii dar conexiunea fiind full-
duplex transferul de date icircn celălalt sens poate continua (această situaţie e denumită half-close)
O icircnchidere completă a unei conexiuni TCP presupune următorii paşi
1 Clientul trimite un segment cu flag-ul FIN activat solicitacircnd icircnchiderea conexiunii
2 Serverul trimite un segment ACK confirmacircnd primirea cererea Numărul de confirmare
se completează normal ca numărul de secvenţă primit + 1
3 Serverul continuă să trimită date către client şi cacircnd doreşte să icircnchidă şi el conexiunea
trimite un segment cu FIN activat
4 Clientul trimite un pachet ACK confirmacircnd icircnchiderea conexiunii
Cel care iniţiază primul procedura de icircnchidere (trimite primul FIN) realizează o icircnchidere activă
(active close) iar celălalt capăt o icircnchidere pasivă (passive close) Icircn mod normal cel care
realizează iniţierea activă va fi primul ce va trimite FIN dar oricare dintre cei doi poate icircnchide
activ conexiunea
Subsections
2 Terminarea simultană
3 Resetarea conexiunii
2 Terminarea simultană
Icircn mod similar cu deschiderea simultană există posibilitatea ca ambele capete ale conexiunii TCP
să iniţieze simultan procedura de icircnchidere a conexiunii Icircn acest caz ambele părţi vor trimite
FIN şi vor aştepta primirea unui ACK Icircn continuare fiecare va primi cererea de terminare şi va
trimite ACK Se observă că numărul de segmente transferate pentru realizarea icircnchiderii
conexiunii (4 segmente) este acelaşi ca la terminarea normală
3 Resetarea conexiunii
Există situaţii icircn care TCP doreşte resetarea conexiunii De exemplu dacă se solicită iniţierea
unei conexiuni la un port inexistent Icircn acest caz cealaltă parte va trimite un segment cu bitul
RST setat pentru a anula solicitarea O altă situaţie este atunci cacircnd se constată că celalalt capăt
al conexiunii nu răspunde un anumit timp (timeout)
Diagrama de stări
Toate evenimentele ce au loc icircn timpul stabilirii conexiunii transferului şi icircnchiderii conexiunii
pot fi rezumate printr-un automat finit cunoscut sub numele de diagrama de stări După cum
chiar numele sugerează este o maşină cu un număr limitat de stări O stare este păstrată pacircnă icircn
momentul apariţiei unui eveniment moment icircn care se poate trece icircn altă stare şisau efectua o
acţiune
Aceste stări posibile sunt (denumirile sunt asemănătoare cu cele utilizate de netstat) cele din
tabelul 71
Tabela Stările diagramei de stări TCP
Stare Descriere
CLOSED Nu există conexiune
LISTEN Serverul aşteaptă cereri de la clienţi
SYN_SENT Cerere de iniţiere (activă) a conexiunii Se
aşteaptă confirmarea
SYN_RCVD S-a primit o cerere de iniţiere conexiune
ESTABLISHED S-a stabilit conexiunea
FIN_WAIT_1 Aplicaţia a solicitat icircnchiderea conexiunii
FIN_WAIT_2 Serverul a acceptat icircnchiderea conexiunii
CLOSING Ambele părţi solicită simultan icircnchiderea
conexiunii
TIME_WAIT Conexiune icircnchisă dar se aşteaptă ca
pachetele retransmise să dispară
CLOSE_WAIT Serverul aşteaptă icircnchiderea dinspre partea
aplicaţiei
LAST_ACK Serverul a icircnchis conexiunea Aşteaptă
ultima confirmare
Icircn diagrama ilustrată icircn figura 74 putem observa 3 tipuri de tranziţii icircntre cele 11 stări tranziţii
ce corespund unei funcţionări normale pentru client (linii normale continue) pentru server (linii
normale icircntrerupte) şi tranziţii pentru situaţii nestandard (linii subţiri continue)
O comportarea normală pentru client presupune parcurgerea următoarelor stări CLOSED
SYN_SEND ESTABLISHED FIN_WAY_1 FIN_WAY_2 TIME_WAIT
Iniţial clientul TCP se află icircn starea CLOSED
Aşteptacircnd icircn starea CLOSED clientul poate primi de la aplicaţie o cerere de iniţiere
activă a unei conexiuni Trimite un segment SYN şi trece icircn starea SYN_SENT
Icircn starea SYN_SENT clientul aşteaptă de la server un segment ACK+SYN după care
trimite un ACK şi trece icircn starea ESTABLISHED Din acest moment poate icircncepe
transferul efectiv de date Clientul va rămacircne icircn această stare cacirct timp are de trimisprimit
date
Aflat icircn această stare clientul TCP poate primi din partea aplicaţiei o cerere de icircnchidere a
conexiunii Icircn acest caz va trimit un segment FIN şi trece icircn starea FIN_WAIT_1
Icircn această stare clientul aşteaptă ACK din partea serverului După ce-l primeşte
conexiunea icircntr-un sens se va icircnchide şi clientul trece icircn starea FIN_WAIT_2
Starea FIN_WAIT_2 durează pacircnă cacircnd primeşte cererea de icircnchidere a conexiunii FIN
din partea serverului Trimite ACK şi va trece icircn starea TIME_WAIT
Icircn această stare se va porni un timer cu valoarea setată la dublul timpului de viaţă estimat
pentru un segment de lungime maximă MSL (Maximum Segment Lifetime) Acest timer
permite retransmiterea ACK-ului icircn cazul icircn care acesta se pierde (celălalt capăt va da
timeout şi va retransmite segmentul FIN) Icircn tot acest time cei doi sockeţi (de la client şi
server) nu vor putea fi reutilizaţi Totodată pachetele icircntacircrziate care sosesc icircn această
perioadă sunt ignorate După expirarea acestui timer clientul revine icircn starea iniţială
CLOSED
Din punctul de vedere al unui server o comportare standard parcurge următoarele stări
CLOSED LISTEN SYN_RCVD ESTABLISHED CLOSE_WAIT şi LAST_ACK
Iniţial serverul TCP se află icircn starea CLOSED
Icircn această stare poate primi de la aplicaţia server o cerere de iniţiere activă şi trece icircn
starea LISTEN
Aflat icircn starea LISTEN serverului TCP poate recepţiona un segment SYN de la un client
TCP Icircn acest caz va trimite ACK+SYN şi va trece icircn starea SYN_RCVD
Icircn această stare serverul aşteaptă primirea confirmării de la client moment icircn care
conexiunea e stabilită icircn ambele sensuri şi se poate icircncepe transferul de date (starea
ESTABLISHED)
Clientul TCP poate solicita icircnchiderea conexiunii trimiţacircnd un segment FIN către server
Icircn acest caz serverul TCP trimite confirmarea şi trece icircn starea CLOSE_WAIT
Icircn această stare serverul aşteaptă să primească din partea programului server icircnchiderea
conexiunii moment icircn care va trimite către client un segment FIN şi trece icircn starea
LAST_ACK
Serverul aşteaptă primirea ultimei confirmări de la client după care revine icircn starea
CLOSED
Atacirct serverul cacirct şi clientul TCP se pot afla icircn oricare din cele 11 stări ale diagramei
Figura Diagrama de stări pentru TCP
4 Controlul fluxului
Dacă icircncă de la icircnceput s-a reuşit stabilirea formatului unui pachet TCP şi a modulului icircn care
trebuie să se facă icircnchiderea şi deschiderea unei conexiuni nu acelaşi lucru se poate spune şi
despre modul icircn care ar trebui să se realizeze controlul fluxului Ţinacircnd seama icircnsă că din 1989
(de cacircnd datează RFC-ul 2581 cel despre care am menţionat că specifică icircn mod clar modul icircn
care trebuie să se comporte o implementare de TCP) TCP-ul a rămas neschimbat putem să icircl
considerăm un rezultat important al domeniului reţelor de calculatoare
Icircn cele ce urmează vom icircnţelege prin controlul fluxului totalitatea algoritmilor care permit
atingerea unei viteze de transfer punct-la-punct cacirct mai mare pentru toate conexiunile existente
Icircn principal aceşti algoritmi stabilesc modul icircn care segmentele şi confirmările trebuie trimise şi
ce acţiuni trebuie executate icircn situaţiile icircn care răspunsurile aşteptate de la celălalt capăt icircntacircrzie
să vină
Subsections
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
Icircntacircrzierea confirmărilor
O modalitate simplă de generare a confirmărilor este de a trimite cacircte una pentru fiecare segment
primit Această politică prezintă avantajul de a face comunicaţia self-clocking icircnsă este
ineficientă dacă segmentele care nu conţin decacirct confirmări sunt urmate la scurtă distanţă (cacircteva
zeci de milisecunde) de segmente ce conţin date efective Pentru a evita această situaţie se
procedează2 la icircntacircrzierea (200ms este o valoare uzuală icircn RFC 1122 se specifică o valoare
maximă de 500ms) a segmentelor care conţin doar confirmări Această strategie face posibil ca
un răspuns generat de primirea unor date să plece sper celălalt capăt icircn acelaşi segment cu
confirmarea
Observaţie deoarece este dificil de menţinut timere pentru fiecare confirmare diferenţa de
200ms este calculată de un timer global Din acest motiv modul efectiv de comportare poate fi
descris şi icircn felul următor cacircnd un segment nu conţine decacirct o confirmare el este pus icircntr-o
coadă ce va fi inspectată de un proces care din 200 icircn 200 ms trimite tot ce s-a acumulat icircn
coada
Footnotes
2
Acest comportament a fost propus de David D Clark icircn iulie 1982 icircn RFC 813
Algoritmul Nagle
Acest algoritm3 icircncearcă să icircmbunătăţească performanţele exploatacircnd următoarea caracteristică
foarte des icircntacirclnită icircn dialogul dintre două staţii dacă se icircncearcă trimiterea unor date de
dimensiune mică icircnsă există icircncă date neconfirmate de partener atunci ele sunt buffer-ate şi
trimise icircntr-un segment mai mare cacircnd soseşte confirmarea aşteptată Icircn acest fel se poate evita
generarea datagramelor mici (tinygrame) icircn situaţia unei legături lente Icircn cazul unei legături
rapide confirmările vor veni repede şi icircntacircrzierea introdusă de algoritm va neglijabilă
Există icircnsă şi cazuri icircn care acest algoritm duce la deprecierea performanţelor mesajele scurte
generate de mişcările mouse-ului icircn cazul folosirii unui server X Window sau utilizarea tastelor
care trimit mai mult de un caracter (secvenţe escape) Pentru a rezolva aceste inconveninte API-
ul de utilizare a TCP-ului trebuie să ofere o modalitate de a dezactiva acest algoritm (icircn sistemele
bazate pe sockeţi există icircn acest scop opţiunea TCP_NODELAY)
Footnotes
algoritm3
Algoritmul aparţinacircnd lui John Nagle a fost propus icircn ianuarie 1984 icircn RFC 896
Fereastra glisantă
Algoritmul implementat de TCP pentru a implementa transferul sigur de date este cunoscut icircn
teorie sub numele de Go-Back-N Icircn acest algoritm se utilizează numere de secvenţă pentru a
distinge pachetele icircntre ele şi o coadă (dimensiunea maximă a cozii reprezintă fereastra) de
pachetele a căror confirmare se aşteaptă Pachetele se icircmpart icircn 4 categorii
1 pachete trimis şi pentru care s-a primit confirmare
2 pachete trimise şi pentru care se aşteaptă icircncă confirmarea
3 pachete care nu au fost trimise icircncă dar care nu depăşesc limitele ferestrei şi deci pot fi
trimise
4 pachete care icircncă nu au fost trimite şi care nici nu vor putea fi trimise decacirct după ce au
fost trimise toate pachetele din categoria 3 şi s-au primit o parte din confirmările la
pachetele din categoria 2
Dacă confirmările pentru pachetele din categoria 2 icircntacircrzie prea mult (un mecanism de timer-e
informează asupra acestui lucru) atunci ele vor fi retrimise Icircn versiunea iniţială TCP-ul nu
permitea decacirct confirmări pozitive ceea ce icircnseamnă că avansarea ferestrei se va icircmpotmoli la
segmentele neconfirmate Cum se poate evita aceasta situaţie vom discuta icircn detaliu icircn capitolele
următoare O soluţie foarte radicală o constituie introducerea de confirmări selective (acest lucru
este realizat de RFC 2018 din octombrie 1996) Această modifică face ca TCP-ul actual să fie un
hibrid de Go-Back-N şi Selective Repeat
Deoarece dimensiunea ferestrei este anunţată la fiecare segment un client lent poate ca pe măsură
ce trimite confirmările să informeze despre progresul icircnregistrat la livrarea datelor următorului
nivel (aplicaţie) Dacă datele vin prea repede pentru viteza cu care clientul procesează datele
fereastra fereastra se va dimiua şi chiar icircnchide (acest lucru se realizează anunţacircnd o fereastră de
dimensiune zero) Cum se realizează efectiv redeschiderea vom analiza icircntr-un capitol viitor
Slow start
Un transfer de date TCP poate să icircnceapă prin transmiterea de segmente pacircnă la umplerea
icircntregii ferestre după care fie se primesc confirmări care vor permite unor noi pachete să fie
trimise fie vor expira timer-ele de retransmisie şi se va icircncepe retrimiterea pachetelor de la
icircnceputul ferestrei Din păcate un astfel de comportament poate duce la pomparea icircn reţea a unui
număr de pachete prea mare pentru capacitatea disponibilă efectiv icircnrăutăţind congestia Pentru
a evita acest lucru s-a propus următoarea soluţie4 iniţial se trimite un segment după primirea
confirmării lui se trimit două segmente după sosirea confirmărilor pentru ele se trimit patru
segmente şi aşa mai departe La un moment dat fie vor icircncepe să se piardă segmente (un indiciu
că s-a atins capacitatea maximă a canalului) fie se va umple fereastra pe care o anunţă cel care
primeşte Trebuie să remarcam că datorită creşterii exponenţiale a numărului de segmente se va
atinge destul de repede una din cele două situaţii
Modalitatea efectivă de implementare a acestui algoritm are la bază utilizarea unei ferestre de
congestie (congestion window cwnd) care este iniţializată cu dimensiunea unui segment (cwnd
se calculează icircn octeţi) şi la fiecare pas este dublată fereastra efectivă din cadrul căreia se pot
trimite segmente este dată de minimul dintre ultima fereastra comunicată de partener şi cwnd
Footnotes
soluţie4
Soluţia aparţine lui V Jacobson şi a fost prezentată icircn 1988 la conferinţă ACM
SIGCOMM-88
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Deoarece TCP trebuie să funcţioneze icircn condiţii variate de latenţă modul icircn care se face
retransmiterea trebuie să fie cacirct mai flexibil (şi simplu icircn acelaşi timp pentru a introduce un
overhead cacirct mai mic) Timpul cacirct se aşteaptă venirea unei confirmări (retransmission timeout
RTO) este calculat prin cronometrarea timpului care icirci ia unui segment trimis să fie confirmat
Pentru o anumită conexiune se cronometrează cacircte un singur segment la un moment dat iar pe
baza RTT-ului măsurat se actualizează valoare RTO-ului
Icircn RFC 793 formula de calcul a RTO-ului este următoarea
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
Figura Opţiuni TCP
3 Iniţierea şi terminarea unei conexiuni TCP
TCP este un protocol orientat conexiune deci presupune stabilirea unei căi virtuale icircntre sursă şi
destinaţie
Subsections
Protocolul de iniţiere
o 1 Deschiderea simultană
Protocolul de terminare
o 2 Terminarea simultană
o 3 Resetarea conexiunii
Diagrama de stări
Protocolul de iniţiere
Modul de transmisie icircn cazul protocolului TCP este full-duplex deci sunt transmise date
simultan icircn ambele direcţii Aceasta presupune că cel care iniţiază conexiunea trebuie să
primească aprobarea celuilalt capăt icircnainte de icircnceperea transferului de date sursa icircşi anunţă
intenţia de a iniţia o conexiune destinaţia trimite un pachet cu confirmarea cererii şi un pachet de
iniţiere a conexiunii de la el la sursă iar apoi sursa confirmă cererea primită de la destinaţie Paşii
2 şi 3 pot fi realizaţi prin trimiterea unui singur pachet de aceea protocolul de iniţiere este
cunoscut sub numele de three-way handshake
Icircn cadrul protocolului de iniţiere există 2 tipuri de cereri de iniţiere cerere activă (active open)
iniţiată de clientul ce doreşte să stabilească conexiunea cu serverul şi cerere pasivă (passive
open) din partea serverului
Cei 3 paşi sunt
1 Clientul trimite un segment cu flag-ul SYN setat şi care conţine portul sursă portul de la
destinaţie şi numărul de secvenţă generat iniţial (ISN) de la care se vor numerota octeţii
de la client către server Opţional se pot stabili parametrii conexiunii prin setarea lungimii
maxime a segmentelor (MSS) dispus să le primească de la server factorului de scalare a
ferestrei Acest prim segment nu conţine nici un parametru de confirmare şi de asemenea
nu are rost să conţine să seteze dimensiunea ferestrei
2 Al doilea segment e trimis de server şi are un rol dublu confirmă segmentul primit de la
client prin setarea flag-ului ACK şi completează numărul de secvenţă cu numărul de
secvenţă primit plus 1 şi al doilea rol iniţializează conexiunea de la el către client prin
setarea flag-ului SYN şi generarea unui număr de secvenţă iniţial ce va fi folosit icircn
numerotarea octeţilor de la server spre client Pe lacircngă aceasta trebuie să conţină
dimensiunea ferestrei şi opţional poate seta factorul de scalare şi dimensiunea maximă a
segmentului acceptat
3 Clientul trimite un segment cu confirmarea cererii din partea serverului (ACK setat +
completează numărul confirmat cu numărul de secvenţa primit + 1) Ca şi icircn cazul
pasului 2 trebuie să seteze dimensiunea ferestrei Acest pachet poate conţine date
Subsections
1 Deschiderea simultană
1 Deschiderea simultană
Se poate icircntacircmpla ca uneori cele două capete care vor să comunice să icircncerce să stabilească
conexiunea simultan Icircn acest caz după ce fiecare a trimis segmentul de iniţiere (iniţiere activă)
ambele vor trimite un segment cu SYN + ACK şi se va stabili o singură conexiune nu două
Protocolul de terminare
Oricare dintre cele două părţi poate solicita icircnchiderea conexiunii dar conexiunea fiind full-
duplex transferul de date icircn celălalt sens poate continua (această situaţie e denumită half-close)
O icircnchidere completă a unei conexiuni TCP presupune următorii paşi
1 Clientul trimite un segment cu flag-ul FIN activat solicitacircnd icircnchiderea conexiunii
2 Serverul trimite un segment ACK confirmacircnd primirea cererea Numărul de confirmare
se completează normal ca numărul de secvenţă primit + 1
3 Serverul continuă să trimită date către client şi cacircnd doreşte să icircnchidă şi el conexiunea
trimite un segment cu FIN activat
4 Clientul trimite un pachet ACK confirmacircnd icircnchiderea conexiunii
Cel care iniţiază primul procedura de icircnchidere (trimite primul FIN) realizează o icircnchidere activă
(active close) iar celălalt capăt o icircnchidere pasivă (passive close) Icircn mod normal cel care
realizează iniţierea activă va fi primul ce va trimite FIN dar oricare dintre cei doi poate icircnchide
activ conexiunea
Subsections
2 Terminarea simultană
3 Resetarea conexiunii
2 Terminarea simultană
Icircn mod similar cu deschiderea simultană există posibilitatea ca ambele capete ale conexiunii TCP
să iniţieze simultan procedura de icircnchidere a conexiunii Icircn acest caz ambele părţi vor trimite
FIN şi vor aştepta primirea unui ACK Icircn continuare fiecare va primi cererea de terminare şi va
trimite ACK Se observă că numărul de segmente transferate pentru realizarea icircnchiderii
conexiunii (4 segmente) este acelaşi ca la terminarea normală
3 Resetarea conexiunii
Există situaţii icircn care TCP doreşte resetarea conexiunii De exemplu dacă se solicită iniţierea
unei conexiuni la un port inexistent Icircn acest caz cealaltă parte va trimite un segment cu bitul
RST setat pentru a anula solicitarea O altă situaţie este atunci cacircnd se constată că celalalt capăt
al conexiunii nu răspunde un anumit timp (timeout)
Diagrama de stări
Toate evenimentele ce au loc icircn timpul stabilirii conexiunii transferului şi icircnchiderii conexiunii
pot fi rezumate printr-un automat finit cunoscut sub numele de diagrama de stări După cum
chiar numele sugerează este o maşină cu un număr limitat de stări O stare este păstrată pacircnă icircn
momentul apariţiei unui eveniment moment icircn care se poate trece icircn altă stare şisau efectua o
acţiune
Aceste stări posibile sunt (denumirile sunt asemănătoare cu cele utilizate de netstat) cele din
tabelul 71
Tabela Stările diagramei de stări TCP
Stare Descriere
CLOSED Nu există conexiune
LISTEN Serverul aşteaptă cereri de la clienţi
SYN_SENT Cerere de iniţiere (activă) a conexiunii Se
aşteaptă confirmarea
SYN_RCVD S-a primit o cerere de iniţiere conexiune
ESTABLISHED S-a stabilit conexiunea
FIN_WAIT_1 Aplicaţia a solicitat icircnchiderea conexiunii
FIN_WAIT_2 Serverul a acceptat icircnchiderea conexiunii
CLOSING Ambele părţi solicită simultan icircnchiderea
conexiunii
TIME_WAIT Conexiune icircnchisă dar se aşteaptă ca
pachetele retransmise să dispară
CLOSE_WAIT Serverul aşteaptă icircnchiderea dinspre partea
aplicaţiei
LAST_ACK Serverul a icircnchis conexiunea Aşteaptă
ultima confirmare
Icircn diagrama ilustrată icircn figura 74 putem observa 3 tipuri de tranziţii icircntre cele 11 stări tranziţii
ce corespund unei funcţionări normale pentru client (linii normale continue) pentru server (linii
normale icircntrerupte) şi tranziţii pentru situaţii nestandard (linii subţiri continue)
O comportarea normală pentru client presupune parcurgerea următoarelor stări CLOSED
SYN_SEND ESTABLISHED FIN_WAY_1 FIN_WAY_2 TIME_WAIT
Iniţial clientul TCP se află icircn starea CLOSED
Aşteptacircnd icircn starea CLOSED clientul poate primi de la aplicaţie o cerere de iniţiere
activă a unei conexiuni Trimite un segment SYN şi trece icircn starea SYN_SENT
Icircn starea SYN_SENT clientul aşteaptă de la server un segment ACK+SYN după care
trimite un ACK şi trece icircn starea ESTABLISHED Din acest moment poate icircncepe
transferul efectiv de date Clientul va rămacircne icircn această stare cacirct timp are de trimisprimit
date
Aflat icircn această stare clientul TCP poate primi din partea aplicaţiei o cerere de icircnchidere a
conexiunii Icircn acest caz va trimit un segment FIN şi trece icircn starea FIN_WAIT_1
Icircn această stare clientul aşteaptă ACK din partea serverului După ce-l primeşte
conexiunea icircntr-un sens se va icircnchide şi clientul trece icircn starea FIN_WAIT_2
Starea FIN_WAIT_2 durează pacircnă cacircnd primeşte cererea de icircnchidere a conexiunii FIN
din partea serverului Trimite ACK şi va trece icircn starea TIME_WAIT
Icircn această stare se va porni un timer cu valoarea setată la dublul timpului de viaţă estimat
pentru un segment de lungime maximă MSL (Maximum Segment Lifetime) Acest timer
permite retransmiterea ACK-ului icircn cazul icircn care acesta se pierde (celălalt capăt va da
timeout şi va retransmite segmentul FIN) Icircn tot acest time cei doi sockeţi (de la client şi
server) nu vor putea fi reutilizaţi Totodată pachetele icircntacircrziate care sosesc icircn această
perioadă sunt ignorate După expirarea acestui timer clientul revine icircn starea iniţială
CLOSED
Din punctul de vedere al unui server o comportare standard parcurge următoarele stări
CLOSED LISTEN SYN_RCVD ESTABLISHED CLOSE_WAIT şi LAST_ACK
Iniţial serverul TCP se află icircn starea CLOSED
Icircn această stare poate primi de la aplicaţia server o cerere de iniţiere activă şi trece icircn
starea LISTEN
Aflat icircn starea LISTEN serverului TCP poate recepţiona un segment SYN de la un client
TCP Icircn acest caz va trimite ACK+SYN şi va trece icircn starea SYN_RCVD
Icircn această stare serverul aşteaptă primirea confirmării de la client moment icircn care
conexiunea e stabilită icircn ambele sensuri şi se poate icircncepe transferul de date (starea
ESTABLISHED)
Clientul TCP poate solicita icircnchiderea conexiunii trimiţacircnd un segment FIN către server
Icircn acest caz serverul TCP trimite confirmarea şi trece icircn starea CLOSE_WAIT
Icircn această stare serverul aşteaptă să primească din partea programului server icircnchiderea
conexiunii moment icircn care va trimite către client un segment FIN şi trece icircn starea
LAST_ACK
Serverul aşteaptă primirea ultimei confirmări de la client după care revine icircn starea
CLOSED
Atacirct serverul cacirct şi clientul TCP se pot afla icircn oricare din cele 11 stări ale diagramei
Figura Diagrama de stări pentru TCP
4 Controlul fluxului
Dacă icircncă de la icircnceput s-a reuşit stabilirea formatului unui pachet TCP şi a modulului icircn care
trebuie să se facă icircnchiderea şi deschiderea unei conexiuni nu acelaşi lucru se poate spune şi
despre modul icircn care ar trebui să se realizeze controlul fluxului Ţinacircnd seama icircnsă că din 1989
(de cacircnd datează RFC-ul 2581 cel despre care am menţionat că specifică icircn mod clar modul icircn
care trebuie să se comporte o implementare de TCP) TCP-ul a rămas neschimbat putem să icircl
considerăm un rezultat important al domeniului reţelor de calculatoare
Icircn cele ce urmează vom icircnţelege prin controlul fluxului totalitatea algoritmilor care permit
atingerea unei viteze de transfer punct-la-punct cacirct mai mare pentru toate conexiunile existente
Icircn principal aceşti algoritmi stabilesc modul icircn care segmentele şi confirmările trebuie trimise şi
ce acţiuni trebuie executate icircn situaţiile icircn care răspunsurile aşteptate de la celălalt capăt icircntacircrzie
să vină
Subsections
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
Icircntacircrzierea confirmărilor
O modalitate simplă de generare a confirmărilor este de a trimite cacircte una pentru fiecare segment
primit Această politică prezintă avantajul de a face comunicaţia self-clocking icircnsă este
ineficientă dacă segmentele care nu conţin decacirct confirmări sunt urmate la scurtă distanţă (cacircteva
zeci de milisecunde) de segmente ce conţin date efective Pentru a evita această situaţie se
procedează2 la icircntacircrzierea (200ms este o valoare uzuală icircn RFC 1122 se specifică o valoare
maximă de 500ms) a segmentelor care conţin doar confirmări Această strategie face posibil ca
un răspuns generat de primirea unor date să plece sper celălalt capăt icircn acelaşi segment cu
confirmarea
Observaţie deoarece este dificil de menţinut timere pentru fiecare confirmare diferenţa de
200ms este calculată de un timer global Din acest motiv modul efectiv de comportare poate fi
descris şi icircn felul următor cacircnd un segment nu conţine decacirct o confirmare el este pus icircntr-o
coadă ce va fi inspectată de un proces care din 200 icircn 200 ms trimite tot ce s-a acumulat icircn
coada
Footnotes
2
Acest comportament a fost propus de David D Clark icircn iulie 1982 icircn RFC 813
Algoritmul Nagle
Acest algoritm3 icircncearcă să icircmbunătăţească performanţele exploatacircnd următoarea caracteristică
foarte des icircntacirclnită icircn dialogul dintre două staţii dacă se icircncearcă trimiterea unor date de
dimensiune mică icircnsă există icircncă date neconfirmate de partener atunci ele sunt buffer-ate şi
trimise icircntr-un segment mai mare cacircnd soseşte confirmarea aşteptată Icircn acest fel se poate evita
generarea datagramelor mici (tinygrame) icircn situaţia unei legături lente Icircn cazul unei legături
rapide confirmările vor veni repede şi icircntacircrzierea introdusă de algoritm va neglijabilă
Există icircnsă şi cazuri icircn care acest algoritm duce la deprecierea performanţelor mesajele scurte
generate de mişcările mouse-ului icircn cazul folosirii unui server X Window sau utilizarea tastelor
care trimit mai mult de un caracter (secvenţe escape) Pentru a rezolva aceste inconveninte API-
ul de utilizare a TCP-ului trebuie să ofere o modalitate de a dezactiva acest algoritm (icircn sistemele
bazate pe sockeţi există icircn acest scop opţiunea TCP_NODELAY)
Footnotes
algoritm3
Algoritmul aparţinacircnd lui John Nagle a fost propus icircn ianuarie 1984 icircn RFC 896
Fereastra glisantă
Algoritmul implementat de TCP pentru a implementa transferul sigur de date este cunoscut icircn
teorie sub numele de Go-Back-N Icircn acest algoritm se utilizează numere de secvenţă pentru a
distinge pachetele icircntre ele şi o coadă (dimensiunea maximă a cozii reprezintă fereastra) de
pachetele a căror confirmare se aşteaptă Pachetele se icircmpart icircn 4 categorii
1 pachete trimis şi pentru care s-a primit confirmare
2 pachete trimise şi pentru care se aşteaptă icircncă confirmarea
3 pachete care nu au fost trimise icircncă dar care nu depăşesc limitele ferestrei şi deci pot fi
trimise
4 pachete care icircncă nu au fost trimite şi care nici nu vor putea fi trimise decacirct după ce au
fost trimise toate pachetele din categoria 3 şi s-au primit o parte din confirmările la
pachetele din categoria 2
Dacă confirmările pentru pachetele din categoria 2 icircntacircrzie prea mult (un mecanism de timer-e
informează asupra acestui lucru) atunci ele vor fi retrimise Icircn versiunea iniţială TCP-ul nu
permitea decacirct confirmări pozitive ceea ce icircnseamnă că avansarea ferestrei se va icircmpotmoli la
segmentele neconfirmate Cum se poate evita aceasta situaţie vom discuta icircn detaliu icircn capitolele
următoare O soluţie foarte radicală o constituie introducerea de confirmări selective (acest lucru
este realizat de RFC 2018 din octombrie 1996) Această modifică face ca TCP-ul actual să fie un
hibrid de Go-Back-N şi Selective Repeat
Deoarece dimensiunea ferestrei este anunţată la fiecare segment un client lent poate ca pe măsură
ce trimite confirmările să informeze despre progresul icircnregistrat la livrarea datelor următorului
nivel (aplicaţie) Dacă datele vin prea repede pentru viteza cu care clientul procesează datele
fereastra fereastra se va dimiua şi chiar icircnchide (acest lucru se realizează anunţacircnd o fereastră de
dimensiune zero) Cum se realizează efectiv redeschiderea vom analiza icircntr-un capitol viitor
Slow start
Un transfer de date TCP poate să icircnceapă prin transmiterea de segmente pacircnă la umplerea
icircntregii ferestre după care fie se primesc confirmări care vor permite unor noi pachete să fie
trimise fie vor expira timer-ele de retransmisie şi se va icircncepe retrimiterea pachetelor de la
icircnceputul ferestrei Din păcate un astfel de comportament poate duce la pomparea icircn reţea a unui
număr de pachete prea mare pentru capacitatea disponibilă efectiv icircnrăutăţind congestia Pentru
a evita acest lucru s-a propus următoarea soluţie4 iniţial se trimite un segment după primirea
confirmării lui se trimit două segmente după sosirea confirmărilor pentru ele se trimit patru
segmente şi aşa mai departe La un moment dat fie vor icircncepe să se piardă segmente (un indiciu
că s-a atins capacitatea maximă a canalului) fie se va umple fereastra pe care o anunţă cel care
primeşte Trebuie să remarcam că datorită creşterii exponenţiale a numărului de segmente se va
atinge destul de repede una din cele două situaţii
Modalitatea efectivă de implementare a acestui algoritm are la bază utilizarea unei ferestre de
congestie (congestion window cwnd) care este iniţializată cu dimensiunea unui segment (cwnd
se calculează icircn octeţi) şi la fiecare pas este dublată fereastra efectivă din cadrul căreia se pot
trimite segmente este dată de minimul dintre ultima fereastra comunicată de partener şi cwnd
Footnotes
soluţie4
Soluţia aparţine lui V Jacobson şi a fost prezentată icircn 1988 la conferinţă ACM
SIGCOMM-88
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Deoarece TCP trebuie să funcţioneze icircn condiţii variate de latenţă modul icircn care se face
retransmiterea trebuie să fie cacirct mai flexibil (şi simplu icircn acelaşi timp pentru a introduce un
overhead cacirct mai mic) Timpul cacirct se aşteaptă venirea unei confirmări (retransmission timeout
RTO) este calculat prin cronometrarea timpului care icirci ia unui segment trimis să fie confirmat
Pentru o anumită conexiune se cronometrează cacircte un singur segment la un moment dat iar pe
baza RTT-ului măsurat se actualizează valoare RTO-ului
Icircn RFC 793 formula de calcul a RTO-ului este următoarea
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
dimensiunea ferestrei şi opţional poate seta factorul de scalare şi dimensiunea maximă a
segmentului acceptat
3 Clientul trimite un segment cu confirmarea cererii din partea serverului (ACK setat +
completează numărul confirmat cu numărul de secvenţa primit + 1) Ca şi icircn cazul
pasului 2 trebuie să seteze dimensiunea ferestrei Acest pachet poate conţine date
Subsections
1 Deschiderea simultană
1 Deschiderea simultană
Se poate icircntacircmpla ca uneori cele două capete care vor să comunice să icircncerce să stabilească
conexiunea simultan Icircn acest caz după ce fiecare a trimis segmentul de iniţiere (iniţiere activă)
ambele vor trimite un segment cu SYN + ACK şi se va stabili o singură conexiune nu două
Protocolul de terminare
Oricare dintre cele două părţi poate solicita icircnchiderea conexiunii dar conexiunea fiind full-
duplex transferul de date icircn celălalt sens poate continua (această situaţie e denumită half-close)
O icircnchidere completă a unei conexiuni TCP presupune următorii paşi
1 Clientul trimite un segment cu flag-ul FIN activat solicitacircnd icircnchiderea conexiunii
2 Serverul trimite un segment ACK confirmacircnd primirea cererea Numărul de confirmare
se completează normal ca numărul de secvenţă primit + 1
3 Serverul continuă să trimită date către client şi cacircnd doreşte să icircnchidă şi el conexiunea
trimite un segment cu FIN activat
4 Clientul trimite un pachet ACK confirmacircnd icircnchiderea conexiunii
Cel care iniţiază primul procedura de icircnchidere (trimite primul FIN) realizează o icircnchidere activă
(active close) iar celălalt capăt o icircnchidere pasivă (passive close) Icircn mod normal cel care
realizează iniţierea activă va fi primul ce va trimite FIN dar oricare dintre cei doi poate icircnchide
activ conexiunea
Subsections
2 Terminarea simultană
3 Resetarea conexiunii
2 Terminarea simultană
Icircn mod similar cu deschiderea simultană există posibilitatea ca ambele capete ale conexiunii TCP
să iniţieze simultan procedura de icircnchidere a conexiunii Icircn acest caz ambele părţi vor trimite
FIN şi vor aştepta primirea unui ACK Icircn continuare fiecare va primi cererea de terminare şi va
trimite ACK Se observă că numărul de segmente transferate pentru realizarea icircnchiderii
conexiunii (4 segmente) este acelaşi ca la terminarea normală
3 Resetarea conexiunii
Există situaţii icircn care TCP doreşte resetarea conexiunii De exemplu dacă se solicită iniţierea
unei conexiuni la un port inexistent Icircn acest caz cealaltă parte va trimite un segment cu bitul
RST setat pentru a anula solicitarea O altă situaţie este atunci cacircnd se constată că celalalt capăt
al conexiunii nu răspunde un anumit timp (timeout)
Diagrama de stări
Toate evenimentele ce au loc icircn timpul stabilirii conexiunii transferului şi icircnchiderii conexiunii
pot fi rezumate printr-un automat finit cunoscut sub numele de diagrama de stări După cum
chiar numele sugerează este o maşină cu un număr limitat de stări O stare este păstrată pacircnă icircn
momentul apariţiei unui eveniment moment icircn care se poate trece icircn altă stare şisau efectua o
acţiune
Aceste stări posibile sunt (denumirile sunt asemănătoare cu cele utilizate de netstat) cele din
tabelul 71
Tabela Stările diagramei de stări TCP
Stare Descriere
CLOSED Nu există conexiune
LISTEN Serverul aşteaptă cereri de la clienţi
SYN_SENT Cerere de iniţiere (activă) a conexiunii Se
aşteaptă confirmarea
SYN_RCVD S-a primit o cerere de iniţiere conexiune
ESTABLISHED S-a stabilit conexiunea
FIN_WAIT_1 Aplicaţia a solicitat icircnchiderea conexiunii
FIN_WAIT_2 Serverul a acceptat icircnchiderea conexiunii
CLOSING Ambele părţi solicită simultan icircnchiderea
conexiunii
TIME_WAIT Conexiune icircnchisă dar se aşteaptă ca
pachetele retransmise să dispară
CLOSE_WAIT Serverul aşteaptă icircnchiderea dinspre partea
aplicaţiei
LAST_ACK Serverul a icircnchis conexiunea Aşteaptă
ultima confirmare
Icircn diagrama ilustrată icircn figura 74 putem observa 3 tipuri de tranziţii icircntre cele 11 stări tranziţii
ce corespund unei funcţionări normale pentru client (linii normale continue) pentru server (linii
normale icircntrerupte) şi tranziţii pentru situaţii nestandard (linii subţiri continue)
O comportarea normală pentru client presupune parcurgerea următoarelor stări CLOSED
SYN_SEND ESTABLISHED FIN_WAY_1 FIN_WAY_2 TIME_WAIT
Iniţial clientul TCP se află icircn starea CLOSED
Aşteptacircnd icircn starea CLOSED clientul poate primi de la aplicaţie o cerere de iniţiere
activă a unei conexiuni Trimite un segment SYN şi trece icircn starea SYN_SENT
Icircn starea SYN_SENT clientul aşteaptă de la server un segment ACK+SYN după care
trimite un ACK şi trece icircn starea ESTABLISHED Din acest moment poate icircncepe
transferul efectiv de date Clientul va rămacircne icircn această stare cacirct timp are de trimisprimit
date
Aflat icircn această stare clientul TCP poate primi din partea aplicaţiei o cerere de icircnchidere a
conexiunii Icircn acest caz va trimit un segment FIN şi trece icircn starea FIN_WAIT_1
Icircn această stare clientul aşteaptă ACK din partea serverului După ce-l primeşte
conexiunea icircntr-un sens se va icircnchide şi clientul trece icircn starea FIN_WAIT_2
Starea FIN_WAIT_2 durează pacircnă cacircnd primeşte cererea de icircnchidere a conexiunii FIN
din partea serverului Trimite ACK şi va trece icircn starea TIME_WAIT
Icircn această stare se va porni un timer cu valoarea setată la dublul timpului de viaţă estimat
pentru un segment de lungime maximă MSL (Maximum Segment Lifetime) Acest timer
permite retransmiterea ACK-ului icircn cazul icircn care acesta se pierde (celălalt capăt va da
timeout şi va retransmite segmentul FIN) Icircn tot acest time cei doi sockeţi (de la client şi
server) nu vor putea fi reutilizaţi Totodată pachetele icircntacircrziate care sosesc icircn această
perioadă sunt ignorate După expirarea acestui timer clientul revine icircn starea iniţială
CLOSED
Din punctul de vedere al unui server o comportare standard parcurge următoarele stări
CLOSED LISTEN SYN_RCVD ESTABLISHED CLOSE_WAIT şi LAST_ACK
Iniţial serverul TCP se află icircn starea CLOSED
Icircn această stare poate primi de la aplicaţia server o cerere de iniţiere activă şi trece icircn
starea LISTEN
Aflat icircn starea LISTEN serverului TCP poate recepţiona un segment SYN de la un client
TCP Icircn acest caz va trimite ACK+SYN şi va trece icircn starea SYN_RCVD
Icircn această stare serverul aşteaptă primirea confirmării de la client moment icircn care
conexiunea e stabilită icircn ambele sensuri şi se poate icircncepe transferul de date (starea
ESTABLISHED)
Clientul TCP poate solicita icircnchiderea conexiunii trimiţacircnd un segment FIN către server
Icircn acest caz serverul TCP trimite confirmarea şi trece icircn starea CLOSE_WAIT
Icircn această stare serverul aşteaptă să primească din partea programului server icircnchiderea
conexiunii moment icircn care va trimite către client un segment FIN şi trece icircn starea
LAST_ACK
Serverul aşteaptă primirea ultimei confirmări de la client după care revine icircn starea
CLOSED
Atacirct serverul cacirct şi clientul TCP se pot afla icircn oricare din cele 11 stări ale diagramei
Figura Diagrama de stări pentru TCP
4 Controlul fluxului
Dacă icircncă de la icircnceput s-a reuşit stabilirea formatului unui pachet TCP şi a modulului icircn care
trebuie să se facă icircnchiderea şi deschiderea unei conexiuni nu acelaşi lucru se poate spune şi
despre modul icircn care ar trebui să se realizeze controlul fluxului Ţinacircnd seama icircnsă că din 1989
(de cacircnd datează RFC-ul 2581 cel despre care am menţionat că specifică icircn mod clar modul icircn
care trebuie să se comporte o implementare de TCP) TCP-ul a rămas neschimbat putem să icircl
considerăm un rezultat important al domeniului reţelor de calculatoare
Icircn cele ce urmează vom icircnţelege prin controlul fluxului totalitatea algoritmilor care permit
atingerea unei viteze de transfer punct-la-punct cacirct mai mare pentru toate conexiunile existente
Icircn principal aceşti algoritmi stabilesc modul icircn care segmentele şi confirmările trebuie trimise şi
ce acţiuni trebuie executate icircn situaţiile icircn care răspunsurile aşteptate de la celălalt capăt icircntacircrzie
să vină
Subsections
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
Icircntacircrzierea confirmărilor
O modalitate simplă de generare a confirmărilor este de a trimite cacircte una pentru fiecare segment
primit Această politică prezintă avantajul de a face comunicaţia self-clocking icircnsă este
ineficientă dacă segmentele care nu conţin decacirct confirmări sunt urmate la scurtă distanţă (cacircteva
zeci de milisecunde) de segmente ce conţin date efective Pentru a evita această situaţie se
procedează2 la icircntacircrzierea (200ms este o valoare uzuală icircn RFC 1122 se specifică o valoare
maximă de 500ms) a segmentelor care conţin doar confirmări Această strategie face posibil ca
un răspuns generat de primirea unor date să plece sper celălalt capăt icircn acelaşi segment cu
confirmarea
Observaţie deoarece este dificil de menţinut timere pentru fiecare confirmare diferenţa de
200ms este calculată de un timer global Din acest motiv modul efectiv de comportare poate fi
descris şi icircn felul următor cacircnd un segment nu conţine decacirct o confirmare el este pus icircntr-o
coadă ce va fi inspectată de un proces care din 200 icircn 200 ms trimite tot ce s-a acumulat icircn
coada
Footnotes
2
Acest comportament a fost propus de David D Clark icircn iulie 1982 icircn RFC 813
Algoritmul Nagle
Acest algoritm3 icircncearcă să icircmbunătăţească performanţele exploatacircnd următoarea caracteristică
foarte des icircntacirclnită icircn dialogul dintre două staţii dacă se icircncearcă trimiterea unor date de
dimensiune mică icircnsă există icircncă date neconfirmate de partener atunci ele sunt buffer-ate şi
trimise icircntr-un segment mai mare cacircnd soseşte confirmarea aşteptată Icircn acest fel se poate evita
generarea datagramelor mici (tinygrame) icircn situaţia unei legături lente Icircn cazul unei legături
rapide confirmările vor veni repede şi icircntacircrzierea introdusă de algoritm va neglijabilă
Există icircnsă şi cazuri icircn care acest algoritm duce la deprecierea performanţelor mesajele scurte
generate de mişcările mouse-ului icircn cazul folosirii unui server X Window sau utilizarea tastelor
care trimit mai mult de un caracter (secvenţe escape) Pentru a rezolva aceste inconveninte API-
ul de utilizare a TCP-ului trebuie să ofere o modalitate de a dezactiva acest algoritm (icircn sistemele
bazate pe sockeţi există icircn acest scop opţiunea TCP_NODELAY)
Footnotes
algoritm3
Algoritmul aparţinacircnd lui John Nagle a fost propus icircn ianuarie 1984 icircn RFC 896
Fereastra glisantă
Algoritmul implementat de TCP pentru a implementa transferul sigur de date este cunoscut icircn
teorie sub numele de Go-Back-N Icircn acest algoritm se utilizează numere de secvenţă pentru a
distinge pachetele icircntre ele şi o coadă (dimensiunea maximă a cozii reprezintă fereastra) de
pachetele a căror confirmare se aşteaptă Pachetele se icircmpart icircn 4 categorii
1 pachete trimis şi pentru care s-a primit confirmare
2 pachete trimise şi pentru care se aşteaptă icircncă confirmarea
3 pachete care nu au fost trimise icircncă dar care nu depăşesc limitele ferestrei şi deci pot fi
trimise
4 pachete care icircncă nu au fost trimite şi care nici nu vor putea fi trimise decacirct după ce au
fost trimise toate pachetele din categoria 3 şi s-au primit o parte din confirmările la
pachetele din categoria 2
Dacă confirmările pentru pachetele din categoria 2 icircntacircrzie prea mult (un mecanism de timer-e
informează asupra acestui lucru) atunci ele vor fi retrimise Icircn versiunea iniţială TCP-ul nu
permitea decacirct confirmări pozitive ceea ce icircnseamnă că avansarea ferestrei se va icircmpotmoli la
segmentele neconfirmate Cum se poate evita aceasta situaţie vom discuta icircn detaliu icircn capitolele
următoare O soluţie foarte radicală o constituie introducerea de confirmări selective (acest lucru
este realizat de RFC 2018 din octombrie 1996) Această modifică face ca TCP-ul actual să fie un
hibrid de Go-Back-N şi Selective Repeat
Deoarece dimensiunea ferestrei este anunţată la fiecare segment un client lent poate ca pe măsură
ce trimite confirmările să informeze despre progresul icircnregistrat la livrarea datelor următorului
nivel (aplicaţie) Dacă datele vin prea repede pentru viteza cu care clientul procesează datele
fereastra fereastra se va dimiua şi chiar icircnchide (acest lucru se realizează anunţacircnd o fereastră de
dimensiune zero) Cum se realizează efectiv redeschiderea vom analiza icircntr-un capitol viitor
Slow start
Un transfer de date TCP poate să icircnceapă prin transmiterea de segmente pacircnă la umplerea
icircntregii ferestre după care fie se primesc confirmări care vor permite unor noi pachete să fie
trimise fie vor expira timer-ele de retransmisie şi se va icircncepe retrimiterea pachetelor de la
icircnceputul ferestrei Din păcate un astfel de comportament poate duce la pomparea icircn reţea a unui
număr de pachete prea mare pentru capacitatea disponibilă efectiv icircnrăutăţind congestia Pentru
a evita acest lucru s-a propus următoarea soluţie4 iniţial se trimite un segment după primirea
confirmării lui se trimit două segmente după sosirea confirmărilor pentru ele se trimit patru
segmente şi aşa mai departe La un moment dat fie vor icircncepe să se piardă segmente (un indiciu
că s-a atins capacitatea maximă a canalului) fie se va umple fereastra pe care o anunţă cel care
primeşte Trebuie să remarcam că datorită creşterii exponenţiale a numărului de segmente se va
atinge destul de repede una din cele două situaţii
Modalitatea efectivă de implementare a acestui algoritm are la bază utilizarea unei ferestre de
congestie (congestion window cwnd) care este iniţializată cu dimensiunea unui segment (cwnd
se calculează icircn octeţi) şi la fiecare pas este dublată fereastra efectivă din cadrul căreia se pot
trimite segmente este dată de minimul dintre ultima fereastra comunicată de partener şi cwnd
Footnotes
soluţie4
Soluţia aparţine lui V Jacobson şi a fost prezentată icircn 1988 la conferinţă ACM
SIGCOMM-88
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Deoarece TCP trebuie să funcţioneze icircn condiţii variate de latenţă modul icircn care se face
retransmiterea trebuie să fie cacirct mai flexibil (şi simplu icircn acelaşi timp pentru a introduce un
overhead cacirct mai mic) Timpul cacirct se aşteaptă venirea unei confirmări (retransmission timeout
RTO) este calculat prin cronometrarea timpului care icirci ia unui segment trimis să fie confirmat
Pentru o anumită conexiune se cronometrează cacircte un singur segment la un moment dat iar pe
baza RTT-ului măsurat se actualizează valoare RTO-ului
Icircn RFC 793 formula de calcul a RTO-ului este următoarea
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
trimite ACK Se observă că numărul de segmente transferate pentru realizarea icircnchiderii
conexiunii (4 segmente) este acelaşi ca la terminarea normală
3 Resetarea conexiunii
Există situaţii icircn care TCP doreşte resetarea conexiunii De exemplu dacă se solicită iniţierea
unei conexiuni la un port inexistent Icircn acest caz cealaltă parte va trimite un segment cu bitul
RST setat pentru a anula solicitarea O altă situaţie este atunci cacircnd se constată că celalalt capăt
al conexiunii nu răspunde un anumit timp (timeout)
Diagrama de stări
Toate evenimentele ce au loc icircn timpul stabilirii conexiunii transferului şi icircnchiderii conexiunii
pot fi rezumate printr-un automat finit cunoscut sub numele de diagrama de stări După cum
chiar numele sugerează este o maşină cu un număr limitat de stări O stare este păstrată pacircnă icircn
momentul apariţiei unui eveniment moment icircn care se poate trece icircn altă stare şisau efectua o
acţiune
Aceste stări posibile sunt (denumirile sunt asemănătoare cu cele utilizate de netstat) cele din
tabelul 71
Tabela Stările diagramei de stări TCP
Stare Descriere
CLOSED Nu există conexiune
LISTEN Serverul aşteaptă cereri de la clienţi
SYN_SENT Cerere de iniţiere (activă) a conexiunii Se
aşteaptă confirmarea
SYN_RCVD S-a primit o cerere de iniţiere conexiune
ESTABLISHED S-a stabilit conexiunea
FIN_WAIT_1 Aplicaţia a solicitat icircnchiderea conexiunii
FIN_WAIT_2 Serverul a acceptat icircnchiderea conexiunii
CLOSING Ambele părţi solicită simultan icircnchiderea
conexiunii
TIME_WAIT Conexiune icircnchisă dar se aşteaptă ca
pachetele retransmise să dispară
CLOSE_WAIT Serverul aşteaptă icircnchiderea dinspre partea
aplicaţiei
LAST_ACK Serverul a icircnchis conexiunea Aşteaptă
ultima confirmare
Icircn diagrama ilustrată icircn figura 74 putem observa 3 tipuri de tranziţii icircntre cele 11 stări tranziţii
ce corespund unei funcţionări normale pentru client (linii normale continue) pentru server (linii
normale icircntrerupte) şi tranziţii pentru situaţii nestandard (linii subţiri continue)
O comportarea normală pentru client presupune parcurgerea următoarelor stări CLOSED
SYN_SEND ESTABLISHED FIN_WAY_1 FIN_WAY_2 TIME_WAIT
Iniţial clientul TCP se află icircn starea CLOSED
Aşteptacircnd icircn starea CLOSED clientul poate primi de la aplicaţie o cerere de iniţiere
activă a unei conexiuni Trimite un segment SYN şi trece icircn starea SYN_SENT
Icircn starea SYN_SENT clientul aşteaptă de la server un segment ACK+SYN după care
trimite un ACK şi trece icircn starea ESTABLISHED Din acest moment poate icircncepe
transferul efectiv de date Clientul va rămacircne icircn această stare cacirct timp are de trimisprimit
date
Aflat icircn această stare clientul TCP poate primi din partea aplicaţiei o cerere de icircnchidere a
conexiunii Icircn acest caz va trimit un segment FIN şi trece icircn starea FIN_WAIT_1
Icircn această stare clientul aşteaptă ACK din partea serverului După ce-l primeşte
conexiunea icircntr-un sens se va icircnchide şi clientul trece icircn starea FIN_WAIT_2
Starea FIN_WAIT_2 durează pacircnă cacircnd primeşte cererea de icircnchidere a conexiunii FIN
din partea serverului Trimite ACK şi va trece icircn starea TIME_WAIT
Icircn această stare se va porni un timer cu valoarea setată la dublul timpului de viaţă estimat
pentru un segment de lungime maximă MSL (Maximum Segment Lifetime) Acest timer
permite retransmiterea ACK-ului icircn cazul icircn care acesta se pierde (celălalt capăt va da
timeout şi va retransmite segmentul FIN) Icircn tot acest time cei doi sockeţi (de la client şi
server) nu vor putea fi reutilizaţi Totodată pachetele icircntacircrziate care sosesc icircn această
perioadă sunt ignorate După expirarea acestui timer clientul revine icircn starea iniţială
CLOSED
Din punctul de vedere al unui server o comportare standard parcurge următoarele stări
CLOSED LISTEN SYN_RCVD ESTABLISHED CLOSE_WAIT şi LAST_ACK
Iniţial serverul TCP se află icircn starea CLOSED
Icircn această stare poate primi de la aplicaţia server o cerere de iniţiere activă şi trece icircn
starea LISTEN
Aflat icircn starea LISTEN serverului TCP poate recepţiona un segment SYN de la un client
TCP Icircn acest caz va trimite ACK+SYN şi va trece icircn starea SYN_RCVD
Icircn această stare serverul aşteaptă primirea confirmării de la client moment icircn care
conexiunea e stabilită icircn ambele sensuri şi se poate icircncepe transferul de date (starea
ESTABLISHED)
Clientul TCP poate solicita icircnchiderea conexiunii trimiţacircnd un segment FIN către server
Icircn acest caz serverul TCP trimite confirmarea şi trece icircn starea CLOSE_WAIT
Icircn această stare serverul aşteaptă să primească din partea programului server icircnchiderea
conexiunii moment icircn care va trimite către client un segment FIN şi trece icircn starea
LAST_ACK
Serverul aşteaptă primirea ultimei confirmări de la client după care revine icircn starea
CLOSED
Atacirct serverul cacirct şi clientul TCP se pot afla icircn oricare din cele 11 stări ale diagramei
Figura Diagrama de stări pentru TCP
4 Controlul fluxului
Dacă icircncă de la icircnceput s-a reuşit stabilirea formatului unui pachet TCP şi a modulului icircn care
trebuie să se facă icircnchiderea şi deschiderea unei conexiuni nu acelaşi lucru se poate spune şi
despre modul icircn care ar trebui să se realizeze controlul fluxului Ţinacircnd seama icircnsă că din 1989
(de cacircnd datează RFC-ul 2581 cel despre care am menţionat că specifică icircn mod clar modul icircn
care trebuie să se comporte o implementare de TCP) TCP-ul a rămas neschimbat putem să icircl
considerăm un rezultat important al domeniului reţelor de calculatoare
Icircn cele ce urmează vom icircnţelege prin controlul fluxului totalitatea algoritmilor care permit
atingerea unei viteze de transfer punct-la-punct cacirct mai mare pentru toate conexiunile existente
Icircn principal aceşti algoritmi stabilesc modul icircn care segmentele şi confirmările trebuie trimise şi
ce acţiuni trebuie executate icircn situaţiile icircn care răspunsurile aşteptate de la celălalt capăt icircntacircrzie
să vină
Subsections
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
Icircntacircrzierea confirmărilor
O modalitate simplă de generare a confirmărilor este de a trimite cacircte una pentru fiecare segment
primit Această politică prezintă avantajul de a face comunicaţia self-clocking icircnsă este
ineficientă dacă segmentele care nu conţin decacirct confirmări sunt urmate la scurtă distanţă (cacircteva
zeci de milisecunde) de segmente ce conţin date efective Pentru a evita această situaţie se
procedează2 la icircntacircrzierea (200ms este o valoare uzuală icircn RFC 1122 se specifică o valoare
maximă de 500ms) a segmentelor care conţin doar confirmări Această strategie face posibil ca
un răspuns generat de primirea unor date să plece sper celălalt capăt icircn acelaşi segment cu
confirmarea
Observaţie deoarece este dificil de menţinut timere pentru fiecare confirmare diferenţa de
200ms este calculată de un timer global Din acest motiv modul efectiv de comportare poate fi
descris şi icircn felul următor cacircnd un segment nu conţine decacirct o confirmare el este pus icircntr-o
coadă ce va fi inspectată de un proces care din 200 icircn 200 ms trimite tot ce s-a acumulat icircn
coada
Footnotes
2
Acest comportament a fost propus de David D Clark icircn iulie 1982 icircn RFC 813
Algoritmul Nagle
Acest algoritm3 icircncearcă să icircmbunătăţească performanţele exploatacircnd următoarea caracteristică
foarte des icircntacirclnită icircn dialogul dintre două staţii dacă se icircncearcă trimiterea unor date de
dimensiune mică icircnsă există icircncă date neconfirmate de partener atunci ele sunt buffer-ate şi
trimise icircntr-un segment mai mare cacircnd soseşte confirmarea aşteptată Icircn acest fel se poate evita
generarea datagramelor mici (tinygrame) icircn situaţia unei legături lente Icircn cazul unei legături
rapide confirmările vor veni repede şi icircntacircrzierea introdusă de algoritm va neglijabilă
Există icircnsă şi cazuri icircn care acest algoritm duce la deprecierea performanţelor mesajele scurte
generate de mişcările mouse-ului icircn cazul folosirii unui server X Window sau utilizarea tastelor
care trimit mai mult de un caracter (secvenţe escape) Pentru a rezolva aceste inconveninte API-
ul de utilizare a TCP-ului trebuie să ofere o modalitate de a dezactiva acest algoritm (icircn sistemele
bazate pe sockeţi există icircn acest scop opţiunea TCP_NODELAY)
Footnotes
algoritm3
Algoritmul aparţinacircnd lui John Nagle a fost propus icircn ianuarie 1984 icircn RFC 896
Fereastra glisantă
Algoritmul implementat de TCP pentru a implementa transferul sigur de date este cunoscut icircn
teorie sub numele de Go-Back-N Icircn acest algoritm se utilizează numere de secvenţă pentru a
distinge pachetele icircntre ele şi o coadă (dimensiunea maximă a cozii reprezintă fereastra) de
pachetele a căror confirmare se aşteaptă Pachetele se icircmpart icircn 4 categorii
1 pachete trimis şi pentru care s-a primit confirmare
2 pachete trimise şi pentru care se aşteaptă icircncă confirmarea
3 pachete care nu au fost trimise icircncă dar care nu depăşesc limitele ferestrei şi deci pot fi
trimise
4 pachete care icircncă nu au fost trimite şi care nici nu vor putea fi trimise decacirct după ce au
fost trimise toate pachetele din categoria 3 şi s-au primit o parte din confirmările la
pachetele din categoria 2
Dacă confirmările pentru pachetele din categoria 2 icircntacircrzie prea mult (un mecanism de timer-e
informează asupra acestui lucru) atunci ele vor fi retrimise Icircn versiunea iniţială TCP-ul nu
permitea decacirct confirmări pozitive ceea ce icircnseamnă că avansarea ferestrei se va icircmpotmoli la
segmentele neconfirmate Cum se poate evita aceasta situaţie vom discuta icircn detaliu icircn capitolele
următoare O soluţie foarte radicală o constituie introducerea de confirmări selective (acest lucru
este realizat de RFC 2018 din octombrie 1996) Această modifică face ca TCP-ul actual să fie un
hibrid de Go-Back-N şi Selective Repeat
Deoarece dimensiunea ferestrei este anunţată la fiecare segment un client lent poate ca pe măsură
ce trimite confirmările să informeze despre progresul icircnregistrat la livrarea datelor următorului
nivel (aplicaţie) Dacă datele vin prea repede pentru viteza cu care clientul procesează datele
fereastra fereastra se va dimiua şi chiar icircnchide (acest lucru se realizează anunţacircnd o fereastră de
dimensiune zero) Cum se realizează efectiv redeschiderea vom analiza icircntr-un capitol viitor
Slow start
Un transfer de date TCP poate să icircnceapă prin transmiterea de segmente pacircnă la umplerea
icircntregii ferestre după care fie se primesc confirmări care vor permite unor noi pachete să fie
trimise fie vor expira timer-ele de retransmisie şi se va icircncepe retrimiterea pachetelor de la
icircnceputul ferestrei Din păcate un astfel de comportament poate duce la pomparea icircn reţea a unui
număr de pachete prea mare pentru capacitatea disponibilă efectiv icircnrăutăţind congestia Pentru
a evita acest lucru s-a propus următoarea soluţie4 iniţial se trimite un segment după primirea
confirmării lui se trimit două segmente după sosirea confirmărilor pentru ele se trimit patru
segmente şi aşa mai departe La un moment dat fie vor icircncepe să se piardă segmente (un indiciu
că s-a atins capacitatea maximă a canalului) fie se va umple fereastra pe care o anunţă cel care
primeşte Trebuie să remarcam că datorită creşterii exponenţiale a numărului de segmente se va
atinge destul de repede una din cele două situaţii
Modalitatea efectivă de implementare a acestui algoritm are la bază utilizarea unei ferestre de
congestie (congestion window cwnd) care este iniţializată cu dimensiunea unui segment (cwnd
se calculează icircn octeţi) şi la fiecare pas este dublată fereastra efectivă din cadrul căreia se pot
trimite segmente este dată de minimul dintre ultima fereastra comunicată de partener şi cwnd
Footnotes
soluţie4
Soluţia aparţine lui V Jacobson şi a fost prezentată icircn 1988 la conferinţă ACM
SIGCOMM-88
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Deoarece TCP trebuie să funcţioneze icircn condiţii variate de latenţă modul icircn care se face
retransmiterea trebuie să fie cacirct mai flexibil (şi simplu icircn acelaşi timp pentru a introduce un
overhead cacirct mai mic) Timpul cacirct se aşteaptă venirea unei confirmări (retransmission timeout
RTO) este calculat prin cronometrarea timpului care icirci ia unui segment trimis să fie confirmat
Pentru o anumită conexiune se cronometrează cacircte un singur segment la un moment dat iar pe
baza RTT-ului măsurat se actualizează valoare RTO-ului
Icircn RFC 793 formula de calcul a RTO-ului este următoarea
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
Icircn diagrama ilustrată icircn figura 74 putem observa 3 tipuri de tranziţii icircntre cele 11 stări tranziţii
ce corespund unei funcţionări normale pentru client (linii normale continue) pentru server (linii
normale icircntrerupte) şi tranziţii pentru situaţii nestandard (linii subţiri continue)
O comportarea normală pentru client presupune parcurgerea următoarelor stări CLOSED
SYN_SEND ESTABLISHED FIN_WAY_1 FIN_WAY_2 TIME_WAIT
Iniţial clientul TCP se află icircn starea CLOSED
Aşteptacircnd icircn starea CLOSED clientul poate primi de la aplicaţie o cerere de iniţiere
activă a unei conexiuni Trimite un segment SYN şi trece icircn starea SYN_SENT
Icircn starea SYN_SENT clientul aşteaptă de la server un segment ACK+SYN după care
trimite un ACK şi trece icircn starea ESTABLISHED Din acest moment poate icircncepe
transferul efectiv de date Clientul va rămacircne icircn această stare cacirct timp are de trimisprimit
date
Aflat icircn această stare clientul TCP poate primi din partea aplicaţiei o cerere de icircnchidere a
conexiunii Icircn acest caz va trimit un segment FIN şi trece icircn starea FIN_WAIT_1
Icircn această stare clientul aşteaptă ACK din partea serverului După ce-l primeşte
conexiunea icircntr-un sens se va icircnchide şi clientul trece icircn starea FIN_WAIT_2
Starea FIN_WAIT_2 durează pacircnă cacircnd primeşte cererea de icircnchidere a conexiunii FIN
din partea serverului Trimite ACK şi va trece icircn starea TIME_WAIT
Icircn această stare se va porni un timer cu valoarea setată la dublul timpului de viaţă estimat
pentru un segment de lungime maximă MSL (Maximum Segment Lifetime) Acest timer
permite retransmiterea ACK-ului icircn cazul icircn care acesta se pierde (celălalt capăt va da
timeout şi va retransmite segmentul FIN) Icircn tot acest time cei doi sockeţi (de la client şi
server) nu vor putea fi reutilizaţi Totodată pachetele icircntacircrziate care sosesc icircn această
perioadă sunt ignorate După expirarea acestui timer clientul revine icircn starea iniţială
CLOSED
Din punctul de vedere al unui server o comportare standard parcurge următoarele stări
CLOSED LISTEN SYN_RCVD ESTABLISHED CLOSE_WAIT şi LAST_ACK
Iniţial serverul TCP se află icircn starea CLOSED
Icircn această stare poate primi de la aplicaţia server o cerere de iniţiere activă şi trece icircn
starea LISTEN
Aflat icircn starea LISTEN serverului TCP poate recepţiona un segment SYN de la un client
TCP Icircn acest caz va trimite ACK+SYN şi va trece icircn starea SYN_RCVD
Icircn această stare serverul aşteaptă primirea confirmării de la client moment icircn care
conexiunea e stabilită icircn ambele sensuri şi se poate icircncepe transferul de date (starea
ESTABLISHED)
Clientul TCP poate solicita icircnchiderea conexiunii trimiţacircnd un segment FIN către server
Icircn acest caz serverul TCP trimite confirmarea şi trece icircn starea CLOSE_WAIT
Icircn această stare serverul aşteaptă să primească din partea programului server icircnchiderea
conexiunii moment icircn care va trimite către client un segment FIN şi trece icircn starea
LAST_ACK
Serverul aşteaptă primirea ultimei confirmări de la client după care revine icircn starea
CLOSED
Atacirct serverul cacirct şi clientul TCP se pot afla icircn oricare din cele 11 stări ale diagramei
Figura Diagrama de stări pentru TCP
4 Controlul fluxului
Dacă icircncă de la icircnceput s-a reuşit stabilirea formatului unui pachet TCP şi a modulului icircn care
trebuie să se facă icircnchiderea şi deschiderea unei conexiuni nu acelaşi lucru se poate spune şi
despre modul icircn care ar trebui să se realizeze controlul fluxului Ţinacircnd seama icircnsă că din 1989
(de cacircnd datează RFC-ul 2581 cel despre care am menţionat că specifică icircn mod clar modul icircn
care trebuie să se comporte o implementare de TCP) TCP-ul a rămas neschimbat putem să icircl
considerăm un rezultat important al domeniului reţelor de calculatoare
Icircn cele ce urmează vom icircnţelege prin controlul fluxului totalitatea algoritmilor care permit
atingerea unei viteze de transfer punct-la-punct cacirct mai mare pentru toate conexiunile existente
Icircn principal aceşti algoritmi stabilesc modul icircn care segmentele şi confirmările trebuie trimise şi
ce acţiuni trebuie executate icircn situaţiile icircn care răspunsurile aşteptate de la celălalt capăt icircntacircrzie
să vină
Subsections
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
Icircntacircrzierea confirmărilor
O modalitate simplă de generare a confirmărilor este de a trimite cacircte una pentru fiecare segment
primit Această politică prezintă avantajul de a face comunicaţia self-clocking icircnsă este
ineficientă dacă segmentele care nu conţin decacirct confirmări sunt urmate la scurtă distanţă (cacircteva
zeci de milisecunde) de segmente ce conţin date efective Pentru a evita această situaţie se
procedează2 la icircntacircrzierea (200ms este o valoare uzuală icircn RFC 1122 se specifică o valoare
maximă de 500ms) a segmentelor care conţin doar confirmări Această strategie face posibil ca
un răspuns generat de primirea unor date să plece sper celălalt capăt icircn acelaşi segment cu
confirmarea
Observaţie deoarece este dificil de menţinut timere pentru fiecare confirmare diferenţa de
200ms este calculată de un timer global Din acest motiv modul efectiv de comportare poate fi
descris şi icircn felul următor cacircnd un segment nu conţine decacirct o confirmare el este pus icircntr-o
coadă ce va fi inspectată de un proces care din 200 icircn 200 ms trimite tot ce s-a acumulat icircn
coada
Footnotes
2
Acest comportament a fost propus de David D Clark icircn iulie 1982 icircn RFC 813
Algoritmul Nagle
Acest algoritm3 icircncearcă să icircmbunătăţească performanţele exploatacircnd următoarea caracteristică
foarte des icircntacirclnită icircn dialogul dintre două staţii dacă se icircncearcă trimiterea unor date de
dimensiune mică icircnsă există icircncă date neconfirmate de partener atunci ele sunt buffer-ate şi
trimise icircntr-un segment mai mare cacircnd soseşte confirmarea aşteptată Icircn acest fel se poate evita
generarea datagramelor mici (tinygrame) icircn situaţia unei legături lente Icircn cazul unei legături
rapide confirmările vor veni repede şi icircntacircrzierea introdusă de algoritm va neglijabilă
Există icircnsă şi cazuri icircn care acest algoritm duce la deprecierea performanţelor mesajele scurte
generate de mişcările mouse-ului icircn cazul folosirii unui server X Window sau utilizarea tastelor
care trimit mai mult de un caracter (secvenţe escape) Pentru a rezolva aceste inconveninte API-
ul de utilizare a TCP-ului trebuie să ofere o modalitate de a dezactiva acest algoritm (icircn sistemele
bazate pe sockeţi există icircn acest scop opţiunea TCP_NODELAY)
Footnotes
algoritm3
Algoritmul aparţinacircnd lui John Nagle a fost propus icircn ianuarie 1984 icircn RFC 896
Fereastra glisantă
Algoritmul implementat de TCP pentru a implementa transferul sigur de date este cunoscut icircn
teorie sub numele de Go-Back-N Icircn acest algoritm se utilizează numere de secvenţă pentru a
distinge pachetele icircntre ele şi o coadă (dimensiunea maximă a cozii reprezintă fereastra) de
pachetele a căror confirmare se aşteaptă Pachetele se icircmpart icircn 4 categorii
1 pachete trimis şi pentru care s-a primit confirmare
2 pachete trimise şi pentru care se aşteaptă icircncă confirmarea
3 pachete care nu au fost trimise icircncă dar care nu depăşesc limitele ferestrei şi deci pot fi
trimise
4 pachete care icircncă nu au fost trimite şi care nici nu vor putea fi trimise decacirct după ce au
fost trimise toate pachetele din categoria 3 şi s-au primit o parte din confirmările la
pachetele din categoria 2
Dacă confirmările pentru pachetele din categoria 2 icircntacircrzie prea mult (un mecanism de timer-e
informează asupra acestui lucru) atunci ele vor fi retrimise Icircn versiunea iniţială TCP-ul nu
permitea decacirct confirmări pozitive ceea ce icircnseamnă că avansarea ferestrei se va icircmpotmoli la
segmentele neconfirmate Cum se poate evita aceasta situaţie vom discuta icircn detaliu icircn capitolele
următoare O soluţie foarte radicală o constituie introducerea de confirmări selective (acest lucru
este realizat de RFC 2018 din octombrie 1996) Această modifică face ca TCP-ul actual să fie un
hibrid de Go-Back-N şi Selective Repeat
Deoarece dimensiunea ferestrei este anunţată la fiecare segment un client lent poate ca pe măsură
ce trimite confirmările să informeze despre progresul icircnregistrat la livrarea datelor următorului
nivel (aplicaţie) Dacă datele vin prea repede pentru viteza cu care clientul procesează datele
fereastra fereastra se va dimiua şi chiar icircnchide (acest lucru se realizează anunţacircnd o fereastră de
dimensiune zero) Cum se realizează efectiv redeschiderea vom analiza icircntr-un capitol viitor
Slow start
Un transfer de date TCP poate să icircnceapă prin transmiterea de segmente pacircnă la umplerea
icircntregii ferestre după care fie se primesc confirmări care vor permite unor noi pachete să fie
trimise fie vor expira timer-ele de retransmisie şi se va icircncepe retrimiterea pachetelor de la
icircnceputul ferestrei Din păcate un astfel de comportament poate duce la pomparea icircn reţea a unui
număr de pachete prea mare pentru capacitatea disponibilă efectiv icircnrăutăţind congestia Pentru
a evita acest lucru s-a propus următoarea soluţie4 iniţial se trimite un segment după primirea
confirmării lui se trimit două segmente după sosirea confirmărilor pentru ele se trimit patru
segmente şi aşa mai departe La un moment dat fie vor icircncepe să se piardă segmente (un indiciu
că s-a atins capacitatea maximă a canalului) fie se va umple fereastra pe care o anunţă cel care
primeşte Trebuie să remarcam că datorită creşterii exponenţiale a numărului de segmente se va
atinge destul de repede una din cele două situaţii
Modalitatea efectivă de implementare a acestui algoritm are la bază utilizarea unei ferestre de
congestie (congestion window cwnd) care este iniţializată cu dimensiunea unui segment (cwnd
se calculează icircn octeţi) şi la fiecare pas este dublată fereastra efectivă din cadrul căreia se pot
trimite segmente este dată de minimul dintre ultima fereastra comunicată de partener şi cwnd
Footnotes
soluţie4
Soluţia aparţine lui V Jacobson şi a fost prezentată icircn 1988 la conferinţă ACM
SIGCOMM-88
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Deoarece TCP trebuie să funcţioneze icircn condiţii variate de latenţă modul icircn care se face
retransmiterea trebuie să fie cacirct mai flexibil (şi simplu icircn acelaşi timp pentru a introduce un
overhead cacirct mai mic) Timpul cacirct se aşteaptă venirea unei confirmări (retransmission timeout
RTO) este calculat prin cronometrarea timpului care icirci ia unui segment trimis să fie confirmat
Pentru o anumită conexiune se cronometrează cacircte un singur segment la un moment dat iar pe
baza RTT-ului măsurat se actualizează valoare RTO-ului
Icircn RFC 793 formula de calcul a RTO-ului este următoarea
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
4 Controlul fluxului
Dacă icircncă de la icircnceput s-a reuşit stabilirea formatului unui pachet TCP şi a modulului icircn care
trebuie să se facă icircnchiderea şi deschiderea unei conexiuni nu acelaşi lucru se poate spune şi
despre modul icircn care ar trebui să se realizeze controlul fluxului Ţinacircnd seama icircnsă că din 1989
(de cacircnd datează RFC-ul 2581 cel despre care am menţionat că specifică icircn mod clar modul icircn
care trebuie să se comporte o implementare de TCP) TCP-ul a rămas neschimbat putem să icircl
considerăm un rezultat important al domeniului reţelor de calculatoare
Icircn cele ce urmează vom icircnţelege prin controlul fluxului totalitatea algoritmilor care permit
atingerea unei viteze de transfer punct-la-punct cacirct mai mare pentru toate conexiunile existente
Icircn principal aceşti algoritmi stabilesc modul icircn care segmentele şi confirmările trebuie trimise şi
ce acţiuni trebuie executate icircn situaţiile icircn care răspunsurile aşteptate de la celălalt capăt icircntacircrzie
să vină
Subsections
Icircntacircrzierea confirmărilor
Algoritmul Nagle
Fereastra glisantă
Slow start
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Evitarea congestiei
Fast Retransmission Fast Recovery
Sindromul ``Silly Window
TCP Keepalive Timer
Icircntacircrzierea confirmărilor
O modalitate simplă de generare a confirmărilor este de a trimite cacircte una pentru fiecare segment
primit Această politică prezintă avantajul de a face comunicaţia self-clocking icircnsă este
ineficientă dacă segmentele care nu conţin decacirct confirmări sunt urmate la scurtă distanţă (cacircteva
zeci de milisecunde) de segmente ce conţin date efective Pentru a evita această situaţie se
procedează2 la icircntacircrzierea (200ms este o valoare uzuală icircn RFC 1122 se specifică o valoare
maximă de 500ms) a segmentelor care conţin doar confirmări Această strategie face posibil ca
un răspuns generat de primirea unor date să plece sper celălalt capăt icircn acelaşi segment cu
confirmarea
Observaţie deoarece este dificil de menţinut timere pentru fiecare confirmare diferenţa de
200ms este calculată de un timer global Din acest motiv modul efectiv de comportare poate fi
descris şi icircn felul următor cacircnd un segment nu conţine decacirct o confirmare el este pus icircntr-o
coadă ce va fi inspectată de un proces care din 200 icircn 200 ms trimite tot ce s-a acumulat icircn
coada
Footnotes
2
Acest comportament a fost propus de David D Clark icircn iulie 1982 icircn RFC 813
Algoritmul Nagle
Acest algoritm3 icircncearcă să icircmbunătăţească performanţele exploatacircnd următoarea caracteristică
foarte des icircntacirclnită icircn dialogul dintre două staţii dacă se icircncearcă trimiterea unor date de
dimensiune mică icircnsă există icircncă date neconfirmate de partener atunci ele sunt buffer-ate şi
trimise icircntr-un segment mai mare cacircnd soseşte confirmarea aşteptată Icircn acest fel se poate evita
generarea datagramelor mici (tinygrame) icircn situaţia unei legături lente Icircn cazul unei legături
rapide confirmările vor veni repede şi icircntacircrzierea introdusă de algoritm va neglijabilă
Există icircnsă şi cazuri icircn care acest algoritm duce la deprecierea performanţelor mesajele scurte
generate de mişcările mouse-ului icircn cazul folosirii unui server X Window sau utilizarea tastelor
care trimit mai mult de un caracter (secvenţe escape) Pentru a rezolva aceste inconveninte API-
ul de utilizare a TCP-ului trebuie să ofere o modalitate de a dezactiva acest algoritm (icircn sistemele
bazate pe sockeţi există icircn acest scop opţiunea TCP_NODELAY)
Footnotes
algoritm3
Algoritmul aparţinacircnd lui John Nagle a fost propus icircn ianuarie 1984 icircn RFC 896
Fereastra glisantă
Algoritmul implementat de TCP pentru a implementa transferul sigur de date este cunoscut icircn
teorie sub numele de Go-Back-N Icircn acest algoritm se utilizează numere de secvenţă pentru a
distinge pachetele icircntre ele şi o coadă (dimensiunea maximă a cozii reprezintă fereastra) de
pachetele a căror confirmare se aşteaptă Pachetele se icircmpart icircn 4 categorii
1 pachete trimis şi pentru care s-a primit confirmare
2 pachete trimise şi pentru care se aşteaptă icircncă confirmarea
3 pachete care nu au fost trimise icircncă dar care nu depăşesc limitele ferestrei şi deci pot fi
trimise
4 pachete care icircncă nu au fost trimite şi care nici nu vor putea fi trimise decacirct după ce au
fost trimise toate pachetele din categoria 3 şi s-au primit o parte din confirmările la
pachetele din categoria 2
Dacă confirmările pentru pachetele din categoria 2 icircntacircrzie prea mult (un mecanism de timer-e
informează asupra acestui lucru) atunci ele vor fi retrimise Icircn versiunea iniţială TCP-ul nu
permitea decacirct confirmări pozitive ceea ce icircnseamnă că avansarea ferestrei se va icircmpotmoli la
segmentele neconfirmate Cum se poate evita aceasta situaţie vom discuta icircn detaliu icircn capitolele
următoare O soluţie foarte radicală o constituie introducerea de confirmări selective (acest lucru
este realizat de RFC 2018 din octombrie 1996) Această modifică face ca TCP-ul actual să fie un
hibrid de Go-Back-N şi Selective Repeat
Deoarece dimensiunea ferestrei este anunţată la fiecare segment un client lent poate ca pe măsură
ce trimite confirmările să informeze despre progresul icircnregistrat la livrarea datelor următorului
nivel (aplicaţie) Dacă datele vin prea repede pentru viteza cu care clientul procesează datele
fereastra fereastra se va dimiua şi chiar icircnchide (acest lucru se realizează anunţacircnd o fereastră de
dimensiune zero) Cum se realizează efectiv redeschiderea vom analiza icircntr-un capitol viitor
Slow start
Un transfer de date TCP poate să icircnceapă prin transmiterea de segmente pacircnă la umplerea
icircntregii ferestre după care fie se primesc confirmări care vor permite unor noi pachete să fie
trimise fie vor expira timer-ele de retransmisie şi se va icircncepe retrimiterea pachetelor de la
icircnceputul ferestrei Din păcate un astfel de comportament poate duce la pomparea icircn reţea a unui
număr de pachete prea mare pentru capacitatea disponibilă efectiv icircnrăutăţind congestia Pentru
a evita acest lucru s-a propus următoarea soluţie4 iniţial se trimite un segment după primirea
confirmării lui se trimit două segmente după sosirea confirmărilor pentru ele se trimit patru
segmente şi aşa mai departe La un moment dat fie vor icircncepe să se piardă segmente (un indiciu
că s-a atins capacitatea maximă a canalului) fie se va umple fereastra pe care o anunţă cel care
primeşte Trebuie să remarcam că datorită creşterii exponenţiale a numărului de segmente se va
atinge destul de repede una din cele două situaţii
Modalitatea efectivă de implementare a acestui algoritm are la bază utilizarea unei ferestre de
congestie (congestion window cwnd) care este iniţializată cu dimensiunea unui segment (cwnd
se calculează icircn octeţi) şi la fiecare pas este dublată fereastra efectivă din cadrul căreia se pot
trimite segmente este dată de minimul dintre ultima fereastra comunicată de partener şi cwnd
Footnotes
soluţie4
Soluţia aparţine lui V Jacobson şi a fost prezentată icircn 1988 la conferinţă ACM
SIGCOMM-88
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Deoarece TCP trebuie să funcţioneze icircn condiţii variate de latenţă modul icircn care se face
retransmiterea trebuie să fie cacirct mai flexibil (şi simplu icircn acelaşi timp pentru a introduce un
overhead cacirct mai mic) Timpul cacirct se aşteaptă venirea unei confirmări (retransmission timeout
RTO) este calculat prin cronometrarea timpului care icirci ia unui segment trimis să fie confirmat
Pentru o anumită conexiune se cronometrează cacircte un singur segment la un moment dat iar pe
baza RTT-ului măsurat se actualizează valoare RTO-ului
Icircn RFC 793 formula de calcul a RTO-ului este următoarea
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
Footnotes
2
Acest comportament a fost propus de David D Clark icircn iulie 1982 icircn RFC 813
Algoritmul Nagle
Acest algoritm3 icircncearcă să icircmbunătăţească performanţele exploatacircnd următoarea caracteristică
foarte des icircntacirclnită icircn dialogul dintre două staţii dacă se icircncearcă trimiterea unor date de
dimensiune mică icircnsă există icircncă date neconfirmate de partener atunci ele sunt buffer-ate şi
trimise icircntr-un segment mai mare cacircnd soseşte confirmarea aşteptată Icircn acest fel se poate evita
generarea datagramelor mici (tinygrame) icircn situaţia unei legături lente Icircn cazul unei legături
rapide confirmările vor veni repede şi icircntacircrzierea introdusă de algoritm va neglijabilă
Există icircnsă şi cazuri icircn care acest algoritm duce la deprecierea performanţelor mesajele scurte
generate de mişcările mouse-ului icircn cazul folosirii unui server X Window sau utilizarea tastelor
care trimit mai mult de un caracter (secvenţe escape) Pentru a rezolva aceste inconveninte API-
ul de utilizare a TCP-ului trebuie să ofere o modalitate de a dezactiva acest algoritm (icircn sistemele
bazate pe sockeţi există icircn acest scop opţiunea TCP_NODELAY)
Footnotes
algoritm3
Algoritmul aparţinacircnd lui John Nagle a fost propus icircn ianuarie 1984 icircn RFC 896
Fereastra glisantă
Algoritmul implementat de TCP pentru a implementa transferul sigur de date este cunoscut icircn
teorie sub numele de Go-Back-N Icircn acest algoritm se utilizează numere de secvenţă pentru a
distinge pachetele icircntre ele şi o coadă (dimensiunea maximă a cozii reprezintă fereastra) de
pachetele a căror confirmare se aşteaptă Pachetele se icircmpart icircn 4 categorii
1 pachete trimis şi pentru care s-a primit confirmare
2 pachete trimise şi pentru care se aşteaptă icircncă confirmarea
3 pachete care nu au fost trimise icircncă dar care nu depăşesc limitele ferestrei şi deci pot fi
trimise
4 pachete care icircncă nu au fost trimite şi care nici nu vor putea fi trimise decacirct după ce au
fost trimise toate pachetele din categoria 3 şi s-au primit o parte din confirmările la
pachetele din categoria 2
Dacă confirmările pentru pachetele din categoria 2 icircntacircrzie prea mult (un mecanism de timer-e
informează asupra acestui lucru) atunci ele vor fi retrimise Icircn versiunea iniţială TCP-ul nu
permitea decacirct confirmări pozitive ceea ce icircnseamnă că avansarea ferestrei se va icircmpotmoli la
segmentele neconfirmate Cum se poate evita aceasta situaţie vom discuta icircn detaliu icircn capitolele
următoare O soluţie foarte radicală o constituie introducerea de confirmări selective (acest lucru
este realizat de RFC 2018 din octombrie 1996) Această modifică face ca TCP-ul actual să fie un
hibrid de Go-Back-N şi Selective Repeat
Deoarece dimensiunea ferestrei este anunţată la fiecare segment un client lent poate ca pe măsură
ce trimite confirmările să informeze despre progresul icircnregistrat la livrarea datelor următorului
nivel (aplicaţie) Dacă datele vin prea repede pentru viteza cu care clientul procesează datele
fereastra fereastra se va dimiua şi chiar icircnchide (acest lucru se realizează anunţacircnd o fereastră de
dimensiune zero) Cum se realizează efectiv redeschiderea vom analiza icircntr-un capitol viitor
Slow start
Un transfer de date TCP poate să icircnceapă prin transmiterea de segmente pacircnă la umplerea
icircntregii ferestre după care fie se primesc confirmări care vor permite unor noi pachete să fie
trimise fie vor expira timer-ele de retransmisie şi se va icircncepe retrimiterea pachetelor de la
icircnceputul ferestrei Din păcate un astfel de comportament poate duce la pomparea icircn reţea a unui
număr de pachete prea mare pentru capacitatea disponibilă efectiv icircnrăutăţind congestia Pentru
a evita acest lucru s-a propus următoarea soluţie4 iniţial se trimite un segment după primirea
confirmării lui se trimit două segmente după sosirea confirmărilor pentru ele se trimit patru
segmente şi aşa mai departe La un moment dat fie vor icircncepe să se piardă segmente (un indiciu
că s-a atins capacitatea maximă a canalului) fie se va umple fereastra pe care o anunţă cel care
primeşte Trebuie să remarcam că datorită creşterii exponenţiale a numărului de segmente se va
atinge destul de repede una din cele două situaţii
Modalitatea efectivă de implementare a acestui algoritm are la bază utilizarea unei ferestre de
congestie (congestion window cwnd) care este iniţializată cu dimensiunea unui segment (cwnd
se calculează icircn octeţi) şi la fiecare pas este dublată fereastra efectivă din cadrul căreia se pot
trimite segmente este dată de minimul dintre ultima fereastra comunicată de partener şi cwnd
Footnotes
soluţie4
Soluţia aparţine lui V Jacobson şi a fost prezentată icircn 1988 la conferinţă ACM
SIGCOMM-88
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Deoarece TCP trebuie să funcţioneze icircn condiţii variate de latenţă modul icircn care se face
retransmiterea trebuie să fie cacirct mai flexibil (şi simplu icircn acelaşi timp pentru a introduce un
overhead cacirct mai mic) Timpul cacirct se aşteaptă venirea unei confirmări (retransmission timeout
RTO) este calculat prin cronometrarea timpului care icirci ia unui segment trimis să fie confirmat
Pentru o anumită conexiune se cronometrează cacircte un singur segment la un moment dat iar pe
baza RTT-ului măsurat se actualizează valoare RTO-ului
Icircn RFC 793 formula de calcul a RTO-ului este următoarea
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
nivel (aplicaţie) Dacă datele vin prea repede pentru viteza cu care clientul procesează datele
fereastra fereastra se va dimiua şi chiar icircnchide (acest lucru se realizează anunţacircnd o fereastră de
dimensiune zero) Cum se realizează efectiv redeschiderea vom analiza icircntr-un capitol viitor
Slow start
Un transfer de date TCP poate să icircnceapă prin transmiterea de segmente pacircnă la umplerea
icircntregii ferestre după care fie se primesc confirmări care vor permite unor noi pachete să fie
trimise fie vor expira timer-ele de retransmisie şi se va icircncepe retrimiterea pachetelor de la
icircnceputul ferestrei Din păcate un astfel de comportament poate duce la pomparea icircn reţea a unui
număr de pachete prea mare pentru capacitatea disponibilă efectiv icircnrăutăţind congestia Pentru
a evita acest lucru s-a propus următoarea soluţie4 iniţial se trimite un segment după primirea
confirmării lui se trimit două segmente după sosirea confirmărilor pentru ele se trimit patru
segmente şi aşa mai departe La un moment dat fie vor icircncepe să se piardă segmente (un indiciu
că s-a atins capacitatea maximă a canalului) fie se va umple fereastra pe care o anunţă cel care
primeşte Trebuie să remarcam că datorită creşterii exponenţiale a numărului de segmente se va
atinge destul de repede una din cele două situaţii
Modalitatea efectivă de implementare a acestui algoritm are la bază utilizarea unei ferestre de
congestie (congestion window cwnd) care este iniţializată cu dimensiunea unui segment (cwnd
se calculează icircn octeţi) şi la fiecare pas este dublată fereastra efectivă din cadrul căreia se pot
trimite segmente este dată de minimul dintre ultima fereastra comunicată de partener şi cwnd
Footnotes
soluţie4
Soluţia aparţine lui V Jacobson şi a fost prezentată icircn 1988 la conferinţă ACM
SIGCOMM-88
Retransmission Timeout (RTO) şi Round-Trip Time (RTT)
Deoarece TCP trebuie să funcţioneze icircn condiţii variate de latenţă modul icircn care se face
retransmiterea trebuie să fie cacirct mai flexibil (şi simplu icircn acelaşi timp pentru a introduce un
overhead cacirct mai mic) Timpul cacirct se aşteaptă venirea unei confirmări (retransmission timeout
RTO) este calculat prin cronometrarea timpului care icirci ia unui segment trimis să fie confirmat
Pentru o anumită conexiune se cronometrează cacircte un singur segment la un moment dat iar pe
baza RTT-ului măsurat se actualizează valoare RTO-ului
Icircn RFC 793 formula de calcul a RTO-ului este următoarea
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
unde este ultimul RTT măsurat este o estimare ponderată pentru RTT este un coeficient
de ponderare care icircn general are valoarea iar este un coeficient cu o valoare recomandată
de După cum se poate observa icircn valoarea lui este inclusă icircn mare măsură vechea valoarea
Icircn acest fel ajustarea RTT-ului se face treptat Din păcate acest mod de calcul nu funcţionează
bine la variaţii mari ale RTT-ului ducacircnd la creşterea numărului de retransmisii exact atunci
cacircnd fenomenul de congestie icircncepe să apară
Pentru a remedia aceste neajunsuri V Jacobsen a propus icircn 1988 o nouă metodă de calcul o
metodă care ţine seama seamă şi de modul icircn care variază diferenţa dintre RTT-uri Formulele
folosite sunt următoarele
unde este un estimare pentru media RTT-urilor este o estimare pentru abaterea RTT-urilor
faţă de medie (o aproximaţie suficientă pentru abaterea pătratică medie care icircnsă este mult mai
costisitor de calculat) este diferenţa dintre RTT-ul măsurat ( ) şi estimarea curentă ( )
Coeficientul cu care este actualizată estimarea curentă are valoarea de iar cel cu care este
actualizat estimarea abaterii este La stabilirea unei conexiuni valorile pentru şi sunt
alese astfel icircncacirct să rezulte un RTT de secunde şi un de 3 secunde (aceste recomandări
sunt făcute de RFC 1122)
Dacă pentru un anumit segment nu se primeşte confirmarea icircn intervalul indicat de el va fi
retrimis şi noul este dublat Valoarea maximă admisă pentru este de 240 secunde
Deoarece icircn cazul retrimiterilor nu se poate determina cu exactitate căruia din segmentele trimise
aparţine confirmarea actualizarea estimărilor este amacircnată pacircnă cacircnd se reuşeşte trimiterea
corectă (s-a primit confirmare) fără retransmitere(``din prima) a unui segment Acest artificiu
(deloc neimportant) care permite evitarea actualizarea eronată a estimărilor este cunoscut sub
numele de algoritmul lui Karn şi a fost propus icircn 1987 de P Karn şi C Partridge
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
Evitarea congestiei
Dacă cei doi parteneri care comunică prelucrează datele suficient de repede şi vor să transfere un
volum mare de date atunci limitarea de care se vor lovi este cea dată de viteza reţelei Din cauza
modului ``best-effort pe care IP-ul icircl oferă cacircnd canalul de comunicaţie este saturat o parte din
segmentele TCP se vor pierde Icircn mod poate paradoxal atacirct transmiţătorului cacirct şi receptorul se
pot afla icircn poziţia de a fi primii icircn detectarea pierderii unui segment Unul din indiciile de la
transmiţător care semnalează pierderea unui segment este (icircn mod evident) apariţia 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 icircn varianta iniţială nu
permite decacirct confirmări pozitive singurul lucru pe care receptorul icircl poate face este ca la fiecare
segment out-of-order primit să trimită o confirmare indicacircnd prin aceasta că la el continuă să
vină segmente icircnsă cel indicat de numărul de secvenţă de confirmare lipseşte Primirea acestor
confirmări multiple este al doilea mod icircn care transmiţătorul poate afla de apariţia congestiei
Algoritmul ce trebuie aplicat icircn momentul icircn care se detectează apariţia congestiei este cunoscut
sub numele de ``evitarea congestiei (congestion avoidence) Principiul care stă la baza lui este
ca la apariţia congestiei fie să se treacă la o incrementare liniară a dimensiunii ferestrei dacă
congestia a fost detectată ca urmare a primirii unor confirmări identice repetate fie să se reia
slow start-ul icircn cazul icircn care congestia s-a detectat prin expirarea unui timer de timeout
Implementarea acestui algoritm se bazează pe utilizarea unui nou contor (sstresh) care să indice
dimensiunea ferestrei de la care se trece de la incrementarea exponenţială la cea liniară
Algoritmul efectiv este următorul
1 la stabilirea unei noi conexiuni se pleacă cu sstresh iniţializat la valoare de 64K şi cwnd
la dimensiunea unui segment
2 trimiterea de segmente se face fără a depăşi minimul dintre fereastra publicată de partener
(pentru a nu depăşi capacitatea de procesesare a partenerului) şi cwnd-ul curent (pentru a
nu depăşi limita impusă de capacitatea reţelei)
3 la apariţia congestiei sstresh este setat la jumătatea valorii ferestrei curente (minimul
dintre fereastra anunţată de partener şi cwnd icircnsă cel puţin dimensiunea corespunzătoare
pentru două segmente) dacă congestia a fost detectată prin expirarea unui timer de
timeout atunci cwnd este iniţializat cu dimensiunea unui segment
4 la primirea unei confirmări incrementarea se face icircn două moduri icircn funcţie de relaţie icircn
care se află cwnd şi sstresh
1 dacă cwnd e mai mic sau egal cu sstresh se face incrementarea exponenţială
caracteristică slow start-ului (care de fapt nu e deloc slow icircn cazul de faţă)
2 dacă cwnd e mai mare ca sstresh atunci se face o incrementare cu dimensiunea
unui segment
Fast Retransmission Fast Recovery
După cum am văzut un receptor care primeşte segmente out-of-order va trimite transmiţătorului
confirmări duplicate Algoritmul denumit ``fast retransmission recomandă următoarele două
comportamenet
1 un receptor care detectează segmente out-of order trebuie să nu icircntacircrzie trimiterea de
confirmări (după cum am văzut icircn general confimările sunt icircntacircrziate micşora numărul de
pachete fără date care sunt transferate)
2 un transmiţător care care primeşte mai mult de trei confirmări duplicate trebuie să
retrimită segmentul indicat ca fiind neprimit de confirmările icircn cauză fără a aştepta
expirarea timer-ul de timeout
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
Algoritmul de ``fast recovery icircncearcă să optimizeze şi mai mult comportamentul
transmiţătorului care detectează un număr de trei sau mai multe confimări duplicate Mai exact el
recomandă trecerea la actualizarea liniară a ferestrei (congestion avoidance) Acest tip de
comportament se poate justifica prin următorul raţionament deoarece icircncă mai sunt transferate
date icircntre cei doi parteneri (şi acest lucru se icircntacircmplă sigur de vreme ce sosesc confirmări
duplicate icircn cazul acesta) icircnseamnă că transferul nu este afectat de o congestie severă şi prin
urmare trecerea la slow start nu e (icircncă) necesară (slow start-ul eliberează aproape complet
canalul deoarece cwnd este resetat la dimensiunea unui singur segment)
Cei doi algoritmi pot fi implementaţi icircn felul următor
1 cacircnd se detectează trei confirmări consecutive identice se setează sstresh la jumătate din
valoarea cwnd se retransmite segmentul care s-a pierdut şi se setează cwnd la valoarea
egală cu sstresh plus dimensiunea a trei segmente (acest lucru va face ca algoritmul de
incrementare a cwnd să treacă la incrementare liniară)
2 la fiecare confirmare duplicată care mai soseşte se incrementează cwnd se incrementează
cu dimensiunea unui segment
3 cacircnd icircncetează primirea de confirmări duplicate (segmentul retrimis a ajuns cu bine la
receptor şi s-a trimis o confirmare care acoperă segmentul care se pierduse iniţial) cwnd
este setat la valoarea sstresh
Sindromul ``Silly Window
Protocoalele bazate pe fereastră glisantă (cum este şi TCP-ul) pot să ajungă icircn situaţia deloc
fericită de trimite un număr mare de segmente mici icircn loc de segmente de dimensiune maximă
Acest tip de comportament este cunoscut sub numele de sindromul ``silly window
O modalitate prin care TCP-ul poate să cadă victimă acestui tip de comportament este
deschiderea de ferestre cu dimensiune foarte mică O altă situaţia nefericită este cea icircn care un
transmiţător este ``lacom şi trimite date indiferent de cacirct de mică este fereastra (după cum vom
vedea imediat uneori are sens şi un astfel de comportament) Algoritmul de evitare a acestor
neajunsuri este următorul
1 un receptor nu trebuie să anunţe deschideri de ferestre mici Mai exact nu se recomandă
anunţarea unei incrementări a ferestrei mai mică decacirct dimensiunea unui segment (MSS)
sau jumătate din buffer-ul aflat la dispoziţia receptorului oricare din ele e mai mică
2 un transmiţător va trimite date doar icircn următoarele cazuri
1 se poate trimite un segment icircntreg
2 se poate trimite jumătate din dimensiunea celei mai mari ferestre pe care
partenerul a publicat-o pacircnă acum
3 toate datele trimise pacircnă acum au fost confirmate sau algoritmul Nagle este
dezactivat şi se trimit toate datele care sunt icircn buffer-ul de trimitere
Cacircteva justificări cazul 2b tratează cazul icircn care partenerul anunţă ferestre mai mici decacirct
dimensiunea unui segment iar cazul 2c impune condiţiile respectării algoritmului Nagle după
cum se vede dacă algoritmul Nagle este activ şi s-au acumulat destul date mai exact cacirct
dimensiunea unui segment el va fi trimis chiar dacă există segmente neconfirmate Pentru
implementarea comportamentului impus de 2b un transmiţător trebuie să ţină evidenţa celei mai
mari ferestre pe care partenerul a anunţat-o Ţinacircnd seama că dimensiunea acestor buffer-e nu se
modifică acest mod de a icircncerca determinarea lor este suficient
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
O altă problemă legată tot de ferestre este cazul icircnchiderii acesteia Un mod icircn care s-ar putea
anunţa redeschiderea este trimiterea de către receptor a unei confirmări (duplicat) care să anunţe
redeschiderea la o anumită valoare a ferestrei Deoarece acest pachet nu trebuie confirmat icircn mod
special şi s-ar putea să se piardă se poate ajunge icircn situaţia icircn care receptorul a anunţat
redeschiderea ferestrei segmentul s-a pierdut iar transmiţătorul icircncă mai icircl mai aşteaptă pentru a
putea continua transferul Rezolvarea la această problemă s-a făcut prin impunerea unui alt
comportament
1 transmiţătorul va trimite segmente cu dimensiunea datelor de un octet prin care sondează
deschiderea ferestrei intervalul la care se sondează redeschiderea ferestrei se dublează
(exponenţial backoff) icircn RFC 793 dimensiunea maximă recomandată este de 2 minute
icircnsă icircn RFC 1122 se specifică că maximul este acelaşi cu cel din cazul retransmisiei (240
secunde)
2 receptorul trebuie să refuze aceste pachete răspunzacircnd cu segmente de confirmare care
indică neprimirea octetului respectiv
Observaţie timer-ul special necesar pentru implementare la transmiţător a comportamentului de mai sus este cunoscut sub numele de ``TCP Persistent Timer Numele este justificat de faptul că sondarea deschiderii se va face pacircnă cacircnd fie fereastra se deschide fie conexiunea se icircntrerupe TCP Keepalive Timer
Un lucru interesant despre TCP este faptul că dacă nivelele superioare nu comunică nimic icircntre
ele pentru o perioadă lungă 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 icircn care au trecut cu succes de faza stabilirii legăturii Dacă nivelurile
inferioare (reţeaIP fizic) devin temporar indisponibile cacirct tip cei doi nu vor să comunice atunci
acest lucru nu va perturba icircn nici un fel activitatea şi acest lucru este acceptabil Problemele
icircncep să apară icircn momentul icircn care cei doi doresc să comunice şi nivelele inferioare nu mai
permit acest lucru Evident că cel care va dori să comunice ceva va detecta icircntreruperea legăturii
şi va icircnchide conexiunea Ce se icircntacircmplă icircnsă dacă celălalt capăt nu are nimic de comunicat (de
exemplu este un server care oferă anumite servicii) Pentru el legătura va fi icircn continuare activă
şi icircn general anumite resurse vor fi rezervate pentru aceasta Rezolvarea acestei situaţii este dată
de introducerea unei mecanism de sondare a stării legăturii pe baza unui timer (TCP Keepalive
Timer) care se declanşează din două icircn două ore La fiecare expirare a timer-ului se trimite un
segment fără date care confirmă datele primite pacircnă atunci Răspunsul care trebuie primit este tot
un segment fără date care confirmă datele primite de partener (practic o re-publicare a stării celor
doi parteneri) Dacă răspunsul nu este primit timp de 75 secunde atunci segmentul va fi retrimis
Dacă după 10 astfel de icircncercări tot nu s-a primit nici un răspuns atunci conexiunea se va
considera terminată şi se va anunţa nivelul superior asupra acestui lucru
Observaţii
dacă o staţie primeşte segmente de keepalive despre conexiuni care nu mai sunt active
(de exemplu a fost resetat) atunci va răspunde cu segmente de reset (acesta e un procedeu
standard)
RFC 1122 specifică că facilitatea de keepalive trebuie activată icircn mod explicit
3 Studii de caz
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
Subsections
1 Fragmentarea pachetelor UDP
2 Stabilirea şi eliberarea unei conexiuni TCP
3 Transferul de date TCP
1 Fragmentarea pachetelor UDP
Deoarece UDP-ul este un serviciu fără conexiune toate datele pe care le primeşte de la nivelul
superior sunt icircncapsulate icircntr-o singură datagramă UDP care apoi va forma un pachet IP Dacă
pachetul IP astfel obţinut este prea mare atunci mecanismele IP de fragmentare icircl vor sparge icircn
bucăţi Exemplul următor icircncearcă să studieze exact acest fenomen
Pe maşina athos rulează un server de UDP pe portul 50007 Pe o altă maşină frodo aflată icircn
reţeaua locală este rulat un client care poate fi configurat să trimită un pachet UDP de o anumită
lungime Pentru a putea observa ce se icircntacircmplă pe athos este rulat tcpdump
Deoarece MTU-ul pentru o reţea Ethernet este icircn general 1500 şi antetul IP plus cel UDP ocupă
20 + 8 = 28 octeţi o datagramă UDP de dimensiune 1472 ar trebui sa fie trimisă nefragmentată
Pentru siguranţă folosind clientul de pe athos s-a trimis mai icircntacirci o datagramă UDP cu 1471
octeţi de date şi apoi icircncă una cu 1472 Pentru ambele tcpdump a indicat trimiterea lor fără
fragmentare
182556721144 frodonoi33274 gt athosnoi50007 udp 1471 (DF) (ttl 64 id
51481 len 1499)
182559846764 frodonoi33274 gt athosnoi50007 udp 1472 (DF) (ttl 64 id
51793 len 1500)
La o dimensiune de 1473 ar trebui ca trimiterea să genereze două pachete IP unul care să
conţină primii antetul UDP plus primii 1472 octeţi de date şi icircncă un pachet IP care conţine un
singur octet Iată ce indică tcpdump-ul
182605705813 frodonoi gt athosnoi udp (frag 3627411480) (ttl 64 len
21)
182605706116 frodonoi33274 gt athosnoi50007 udp 1473 (frag
3627414800+) (ttl 64 len 1500)
Intr-adevăr au fost generate două pachete IP
primul conţine doar un singur octet de date şi reprezintă ultimul fragment (bitul de more
fragments este resetat) dintr-o datagrama UDP (din antetul IP se poate determina acest
lucru) care a fost spartă icircn bucăţi deplasamentul octetului primit in datagrama originală
este 1480
al doilea pachet este primul fragment din datagrama UDP şi conţine antetul UDP (din
cauza asta datele efective ocupă doar 1480 octeţi) deplasamentul este 0 şi bitul de more
fragments este setat (acest lucru este indicat de semnul ``+ de după deplasament)
După cum se poate observa ambele pachete poartă acelaşi număr de identificare (36274) Acest
lucru icircmpreună cu informaţiile date de flag-ul more fragments permite reconstrucţia la
destinaţie a datagramei UDP originale O problemă a acestui mod de fragmentare e că icircn cazul
pierderii unui fragment icircntreaga datagramă va fi compromisă şi va trebui retrimisă icircn icircntregime
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
Ce se va icircntacircmpla dacă vom icircncerca să trimitem un datagrama UDP suficient de mare pentru a
necesita spargerea icircn trei bucăţi Iată mai jos un transfer de 2973 de octeţi
132108251495 frodonoi gt athosnoi udp (frag 2352212960) (ttl 64 len
21)
132108251795 frodonoi gt athosnoi udp (frag 2352214801480+) (ttl 64
len 1500)
132108251935 frodonoi32843 gt athosnoi50007 udp 2953 (frag
2352214800+) (ttl 64 len 1500)
După cum se poate observa trimiterea icircn ordine inversă este o caracteristică a sistemului pe care
am testat O datagramă de dimesiune şi mai mare (16273) confirmă acest lucru
132152266391 frodonoi gt athosnoi udp (frag 23523116280) (ttl 64 len
21)
132152266697 frodonoi gt athosnoi udp (frag 23523148014800+) (ttl 64
len 1500)
132152266843 frodonoi gt athosnoi udp (frag 23523148013320+) (ttl 64
len 1500)
132152266976 frodonoi gt athosnoi udp (frag 23523148011840+) (ttl 64
len 1500)
132152267114 frodonoi gt athosnoi udp (frag 23523148010360+) (ttl 64
len 1500)
132152267253 frodonoi gt athosnoi udp (frag 2352314808880+) (ttl 64
len 1500)
132152267391 frodonoi gt athosnoi udp (frag 2352314807400+) (ttl 64
len 1500)
132152267539 frodonoi gt athosnoi udp (frag 2352314805920+) (ttl 64
len 1500)
132152267678 frodonoi gt athosnoi udp (frag 2352314804440+) (ttl 64
len 1500)
132152267819 frodonoi gt athosnoi udp (frag 2352314802960+) (ttl 64
len 1500)
132152267956 frodonoi gt athosnoi udp (frag 2352314801480+) (ttl 64
len 1500)
132152268096 frodonoi32843 gt athosnoi50007 udp 16273 (frag
2352314800+) (ttl 64 len 1500)
2 Stabilirea şi eliberarea unei conexiuni TCP
Pentru a studia modul de stabilire al unei conexiuni TCP vom rula pe o maşină (frodo) un server
de TCP care va asculta pe portul 50007 va accepta fiecare conexiune primită şi o va icircnchide
imediat Clientul va rula pe o altă maşină (alexandra) şi după stabilirea conexiunii va icircnchide la
racircndul său conexiunea Deşi acest lucru ar trebui să ducă la o icircnchidere simultană icircn realitate
vom vedea că are loc o icircnchidere normală
Iată ce arată un tcpdump rulat pe alexandra
[numbers=left]
224647558868 alexandranoi34437 gt frodonoi50007 SWE
24816418282481641828(0)
win 5840 ltmss 1460sackOKtimestamp 10422756 0nopwscale
0gt (DF)
224647559023 frodonoi50007 gt alexandranoi34437 S
15798022861579802286(0) ack 2481641829
win 5792 ltmss 1460sackOKtimestamp 9639913
10422756nopwscale 0gt (DF)
224647559081 alexandranoi34437 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647559435 frodonoi50007 gt alexandranoi34437 F 11(0) ack 1
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
224647560243 alexandranoi34437 gt frodonoi50007 F 11(0) ack 2
win 5840 ltnopnoptimestamp 10422756 9639913gt (DF)
224647560332 frodonoi50007 gt alexandranoi34437 ack 2
win 5792 ltnopnoptimestamp 9639913 10422756gt (DF)
Liniile 1-2 reprezintă segmentul de SYN trimis de clientul de pe alexandra Numărul de
secvenţă este 2481641828 dimensiunea datelor efective este 0 flag-ul de ACK nu este setat
dimensiunea ferestrei este de 5840 octeţi (aceasta corespunde spaţiului ocupat de 4 segmente
TCP conţinacircnd fiecare 1460 octeţi de date) dimensiunea maximă a unui segment (MSS) este de
1460 octeţi (această dimensiune este justificată de faptul că icircntr-un frame Ethernet nu se pot
trimite mai mult de 1500 octeţi şi antetul IP + TCP ocupă 40 de octeţi) Alte informaţii pe care
acest prim segment le conţine staţia este capabilă de a lucra cu notificări explicite referitoare la
congestie (prezentă flagurilor WE indică acest lucru W corespunde flag-ului TCP Congestion
Window Reduced iar E ECN-Echo ECN este acronimul de la Explicit Congestion Notification)
cu confirmări selective (sackOK) cu marcaje de timp (timestamp) şi cu scalări de ferestre
(wscale)
Răspunsul (liniile 3-4) trimis de server-ul (frodo) confirmă primirea segmentului (ack
2481641829) de deschidere de conexiune şi işi publică şi el informaţiile legate de fereastră
MSS timestamp şi scalări ale dimensiunii ferestrei Icircn plus faptul că flag-ul ECN-Echo nu este
setat (E ar fi trebuit să apară lacircngă S) indică faptul că sistemul nu este capabil de ECN
Liniile 5-6 reprezintă ultimul pas din secvenţa de iniţializare confirmarea de către client a
segmentului trimis de server Se poate observa că de aici icircncolo tcpdump-ul afişează valori
relative pentru numere de secvenţă şi cele de confirmare
Mai departe (liniile 7-8) frodo cere icircnchiderea conxiunii (este setat flag-ul de FYN) prin
trimiterea unui segment care nu conţine date dar are un nou număr de secvenţă (e nevoie de aşa
ceva pentru ca partenerul să poată confirma primirea acestui segment) alexandra răspunde
(liniile 9-10) cu un segment care confirmă primirea segmentului de la frodo şi anunţă terminarea
conexiunii şi din capătul lui După ce alexandra confirmă primirea segmentului cele ambele
staţii consideră dialogul icircncheiat
3 Transferul de date TCP
Icircn condiţii similare cu experimentul precedent vom icircncerca să observăm modul icircn care are loc un
transfer simplu de date Serverul va rula pe frodo şi se va comporta ca un reflector după
stabilirea conexiunii aşteaptă primirea unor date pe care apoi le trimite icircnapoi la destinaţie
Clientul va rula pe alexandra şi după stabiliea conexiunii va trimite 8 octeţi de date va aştepta
răspunsul şi apoi va icircnchide conexiunea
Un tcpdump rulat pe alexandra arată următoarele
[numbers=left]
210947449182 alexandranoi35455 gt frodonoi50007 SWE
35311388503531138850(0)
win 5840 ltmss 1460sackOKtimestamp 14016045 0nopwscale
0gt (DF)
210947449326 frodonoi50007 gt alexandranoi35455 S
28332841982833284198(0) ack 3531138851
win 5792 ltmss 1460sackOKtimestamp 13950430
14016045nopwscale 0gt (DF)
210947449374 alexandranoi35455 gt frodonoi50007 ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947449924 alexandranoi35455 gt frodonoi50007 P 19(8) ack 1
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450025 frodonoi50007 gt alexandranoi35455 ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450145 frodonoi50007 gt alexandranoi35455 P 19(8) ack 9
win 5792 ltnopnoptimestamp 13950430 14016045gt (DF)
210947450161 alexandranoi35455 gt frodonoi50007 ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450487 alexandranoi35455 gt frodonoi50007 F 99(0) ack 9
win 5840 ltnopnoptimestamp 14016045 13950430gt (DF)
210947450660 frodonoi50007 gt alexandranoi35455 F 99(0) ack 10
win 5792 ltnopnoptimestamp 13950431 14016045gt (DF)
210947450691 alexandranoi35455 gt frodonoi50007 ack 10
win 5840 ltnopnoptimestamp 14016045 13950431gt (DF)
Primele trei segmente (liniile 1-6) reprezintă o deshidere identică cu cea pe care am studiat-o icircn
cazul precedent Segmentul care apare pe liniile 7-8 reprezintă cei 8 octeţi de date care se doreau
transferaţi Deoarece segmentul conţine toate datele flagul de PUSH este activat După ce datele
au fost recepţionate la server acesta generează un segment fără date (liniile 9-10) şi apoi le
trimite icircnapoi (liniile 10-11) Clientul care le primeşte răspunde cu un segment de confirmare
(liniile 13-14) Mai departe urmează o icircnchidere similară cu cea din exemplu precedent(liniile
15-20)
O observaţie care se poate face pe baza afişării furnizate de tcpdump e că mecanismul de
icircntacircrziere a confirmărilor nu a fost activ Dacă ar fi fost activ atunci confirmarea din segmentul
de pe liniile 13-14 ar fi trebui să facă parte din segmentul de date care urmează imediat (liniile
15-16) O posibilă explicaţie e că frodo e icircncă icircn porţiunea de slow start icircn care nici o
confirmare nu e icircntărziată pentru a deschide cacirct mai repede fereastra de congestie