Cursul 7 - Protocolul UDP. Nivelul Transport
Nivelul Rețea prezintă următoarele neajunsuri:
- nu garantează transmiterea datelor
- nu poate detecta erori de transmisie
- nu păstrează ordinea de transmisie a pachetelor
Protocoalele de nivel Transport își propun remedierea acestor puncte slabe: implementarea lor individualizează procesele locale și ramifică transmisia informației de la host la host prin introducerea porturilor.
Fiecare proces poate fi identificat printr-un port unic, asociat socket-ului deschis de către acesta din urmă. Astfel, este soluționată problema partajării concurente a resurselor de rețea (un proces nu așteaptă încheierea comunicației inițiate de către alte procese).
Obs: ID-ul unui port este reprezentat pe 2 octeți. Totodată, există porturi rezervate anumitor protocoale și servicii de sistem (ID-uri alocate între 0-1024).
Protocolul UDP
-
cel mai simplu protocol de transport
-
oferă light-checking pentru erori
-
nu stabilește o conexiune client-server!
- se trimit direct datagrame
- idee utilă atunci când nu este necesar / este prea costisitor să păstrăm o conexiune activă între entități
-
nu se garantează ordinea/corectitudinea pachetelor trimise (nu există a astfel de etapă de verificare)
-
prezintă overhead mic $\Rightarrow$ ieftin de implementat, dar nesigur
- ex: Header UDP - 8 bytes VS Header TCP - 20 bytes
-
implementat de către Kernel-ul de Linux prin intermediul Socket API-ului; Network-Stack-ul devine responsabil de parsarea datagramelor UDP
Schiță a implementării unui protocol de nivel Transport din Kernel (pseudocod):
vector <int> sockets;
pair <int, int> ports(socket, port);
// (1)
int create_unique_id() {
int new_id = sockets[sockets.size() - 1] + 1;
sockets.push(new_id);
return new_id;
}
// (2)
void bind(int socket, int port) {
ports.push((socket, port));
}
// (3)
void send(int socket, void *data, ... dest) {
UDP_packet pkt;
pkt.data = data;
pkt.port_dst = dest.port;
pkt.port_src = ...; // random source port!
send_ip(pkg, dest.ip);
}
// (4)
int recv(int socket) {
pkt = packets.pop(port);
UDP_packet p = (UDP_packet) pkt;
verify_checksum(pkt);
return p.data;
}
Concluzii UDP:
-
avantajos datorită vitezei
-
complexitate redusă & cost scăzut de implementare
-
pe baza lui se pot dezvolta alte protocoale
Îmbunătățiri posibile
1) Stop-and-Wait
- se adaugă următoarele câmpuri la header-ul pachetelor: sequence_number, type (fiecare pe câte 2 octeți)
- sender-ul trimite o datagramă UDP, așteaptă confirmarea receiver-ului printr-un pachet ACK, apoi trimite următoarea datagramă ș.a.m.d.
- în cazul în care se pierde un pachet ACK, sender-ul așteaptă un interval de timp, după care retrimite pachetul inițial
- dezavantaj: protocolul este unul lent
2) Select-and-Go
- folosește fereastra glisantă
- se trimite un număr de datagrame egal cu dimensiunea ferestrei (fiecare pachet va avea un seq_number asociat)
- pentru fiecare datagramă se așteaptă un ACK de confirmare cu seq_number-ul corespunzător
- dacă se pierde un pachet, ACK-urile primite vor avea seq_number-ul pachetului precedent; pachetul pierdut va fi retrimis, iar fereastra glisantă se va deplasa mai departe