Računarske mreže Čas 2 Ivana Tanasijević e-mail: ivana@matf.bg.ac.rs Matematički fakultet, Beograd 1
Utvrđivanje gradiva sa prethodnog časa: popunjavanje adresne strukture, kreiranje soketa, privezivanje soketa, slanje i prihvatanje paketa. 2
UDP protokol 3
UDP protokol Server pravi UDP soket, popunjava adresnu strukturu informacijama o adresi na kojoj želi da prima pakete, privezuje soket za tu adresu. Klijent pravi UDP soket i popunjava adresnu strukturu informacijama o serveru. UDP soket se kreira socket funkcijom tako što se za tip konekcije postavlja SOCK_DGRAM. Klijent i server ne ostvaruju konekciju, već na dalje šalju jedan drugome pakete navodeći svaki put adresu onoga kome šalju paket. U tu svrhu koriste funkcije sendto i recvfrom Primeri: echo1, daytime1
Gubitak paketa Ako paketi poslati od klijenta ne stignu do servera, klijent će ostati blokiran u recvfrom pozivu. Isto će se desiti i ako server primi pakete, ali odgovor ne stigne do klijenta. Može se postaviti vreme koje će klijent da čeka. Međutim, nije isto da li je nastupila prva ili druga situacija. Primer je transfer novca.
Verifikovanje primljenog odgovora Kada klijent pošalje paket serveru, svako ko zna efemeralni port klijenta može mu odgovoriti, a ne samo izabrani server. Kako se zaštititi od primanja odgovora od bilo koga? Potrebno je da klijent alocira novu adresnu strukturu i da pokazivač na nju prosledi funkciji recvfrom. Tada će se ona popuniti podacima o onom ko je poslao paket. Proverom veličine te adresne strukture i sadržajem funkcijom memcpy, može se dobiti odgovor. Međutim, ovo radi samo ako je server privezao svoj soket za specifičnu IP adresu i port, odnosno ako nije koristio džoker konstantu, u suprotnom verifikacija može biti neuspešna.
Verifikovanje primljenog odgovora Na primer, klijent za slanje koristi adresu koja nije primarna za dati host. Dok kernel na strani servera, za slanje bira primarnu adresu na tom hostu. Jedno rešenje je da klijent proverava ime domena datog hosta, koristeći DNS, umesto da proverava IP adresu. Drugo rešenje je da UDP server kreira po jedan soket za svaku IP adresu na datom hostu, priveže svaki od njih za po jednu adresu, i potom pomoću select funkcije prihvata pakete od klijenata. Kako se na ovaj način svaki paket prihvata preko adrese koja je privezana, to će i odgovor ići preko te adrese.
Ako server nije pokrenut U ovoj situaciji, klijent koji je poslao paket, može da ostane blokiran u recvfrom funkciji čekajući odgovor. Ona nema načina da utvrdi da li je server uopšte dostupan ili ne. Komandom tcpdump možemo da pratimo slanje paketa. Ako pokrenemo tcpdump, zatim i program klijent, u jednom trenutku će se pojaviti poruka: - udp port xyz unreachable Ovakva greška se naziva asinhrona. Ona je prouzrokovana pozivom sendto, ali sendto se uspešno vratila u klijent program.
Asinhrone greške Ovakve asinhrone greške se vraćaju u proces ako se koristi funkcija connect. Funkcija connect asocira soket sa informacijama iz adresne strukture koja joj je prosleđena. Kernel samo čuva IP adresu i port, koji su prosleđeni adresnom strukturom, i vraća se odmah u proces. Razlike su u sledećem: - ne moramo na dalje precizirati adresu servera, možemo da koristimo I funkcije koje nemaju kao argumente adresne strukture, kao što su write ili send, umesto sendto - ne moramo koristiti recvfrom, već možemo read ili recv; ovo nas ograničava da možemo primati pakete samo sa te jedne adrese - asinhrone greške se vraćaju u proces.
Pozivanje connect više puta Kada se connect pozove, može se komunicirati samo sa parom čiju smo adresu naveli (bilo da smo pozvali iz servera ili klijenta). Ako želimo samo da obrišemo adresu koju je kernel zapamtio, odnosno da diskonektujemo soket, pozivamo connect sa konstantom AF_UNSPEC na mesto familije adresa. Funkcija connect će vratiti grešku EAFNOSUPPORT i to je u redu, jer će soket biti diskonektovan. Ako želimo da promenimo IP adresu sa kojom komuniciramo, potrebno je da diskonektujemo soket i ponovo da pozovemo connect sa tom novom adresom. Primer: echo2
Primer: Pozivanje connect kod UDP int count; /* Duzina poruke. */ struct sockaddr_in address; /* Adresa klijenta. */ socklen_t length; /* Duzina gornje adrese. */ /* Ucitava se poruka. */ if ((count = recvfrom (server, bufer, BUFFER_SIZE, 0, (struct sockaddr *) &address, &length)) < 0) error_fatal ("%s recvfrom() error\n", program); /* Prosledjuje se adresa kernelu. */ length = sizeof (address); if (connect (server, (struct sockaddr *) &address, length) < 0) error_fatal ("%s connect() error\n", program); /* Brise se adresa. */ address.sin_family = AF_UNSPEC; if (connect (server, (struct sockaddr *) &address, length) < 0) error_fatal ("%s connect() error\n", program);