Sunteți pe pagina 1din 56

Universitatea Al. I.

Cuza Iai Facultatea de Informatic

tefan-Ciprian Tanas

Re ele de calculatoare

2006

Cuprins

Cuprins ........................................................................................................................... 2 I. Scurt istoric al Internetului .............................................................................. 4 Serviciile Internetului........................................................................................ 7 II. No iuni primare ................................................................................................. 8 Adrese IP............................................................................................................. 9 Clasificarea re elelor de calculatoare............................................................ 10 III. Modelul TCP/IP .............................................................................................15 Nivelul gazd-la-re ea ..................................................................................... 17 Nivelul re ea...................................................................................................... 18 Nivelul transport.............................................................................................. 19 TCP (Transmission Control Protocol)................................................... 19 UDP (User Datagram Protocol).............................................................. 20 Nivelul aplica ie................................................................................................ 21 IV. Comenzi pentru re ele de calculatoare ........................................................22 Comanda ping ............................................................................................. 22 Comanda traceroute................................................................................... 23 Comanda host ............................................................................................. 24 V. Programarea re elelor de calculatoare .........................................................26

Servere i clien i TCP...................................................................................... 30 Servere concurente.......................................................................................... 39 Servere i clien i UDP .................................................................................... 49 Teme de laborator......................................................................................................54 Bibliografie ..................................................................................................................56

I. Scurt istoric al Internetului

n timpul Rzboiului Rece, Departamentul de Aprare a Statelor Unite ale Americii (Department of Defence - DoD) i-a dorit o re ea de comand i control care s poat supravie ui unui rzboi nuclear. Re elele telefonice tradi ionalele erau vulnerabile ntruct foloseau comutarea circuitelor. De exemplu, dac se defecta o linie de transmisie sau un comutator, conversa iile care le utilizau nu mai puteau avea loc i astfel o parte din re ea nu mai era func ional. Departamentul de Aprare a nsrcinat agen ia sa de cercetare, ARPA (Advanced Research Projects Agency - Agen ia de Cercetare pentru Proiecte Avansate), pentru rezolvarea acestei probleme. O perioad ARPA a purtat denumirea de DARPA (Defence Advanced Research Projects Agency - Agen ia de Cercetare pentru Proiecte Avansate de Aprare). ARPA a fost creat ca rspuns la lansarea Sputnik-ului de ctre Uniunea Sovietic n 1957, misiunea ei fiind de dezvoltare a tehnologiilor care puteau fi folosite n scopuri militare. Activitatea ei consta n dirijarea fondurilor pe baz de contracte ctre universit ile i firmelor care aveau idei promi toare. O parte din fonduri au mers ctre universit i cu scopul de a studia comutarea de pachete. Ideea a fost a lui Paul Bran i pe care a publicat-o la nceputul anilor 1960 ntr-o serie de rapoarte ale Corpora iei RAND. Dup consultarea exper ilor, ARPA a decis c Departamentul de Aprare avea nevoie de o re ea cu comutare de pachete. Re eaua era compus din minicalculatoare IMP (Interface Message Processors - procesoare pentru mesaje de interfa ) conectate prin linii de transimie. Din motive de fiabilitate a re elei, fiecare minicalculator trebuia legat direct la cel pu in alte dou minicalculatoare. Astfel, dac pica o linie de transmisie, se putea utiliza ci alternative. Dup realizarea modelului, a trebui s se treaca la implementare. Astfel c 12 companii au depus oferte, din care a fost aleas BBN, o firm de consultan din Cambridge, Massachusetts. n 1968 a fost ncheiat un contract cu aceasta pentru construirea re elei i realizarea de programe pentru re ea. Pentru 4

interconectarea calculatoarelor s-au folosit linii de telefonie de 56kbps de la firmele de telefonie. n anul 1969 ARPA a organizat o ntlnire cu cercettorii din domeniul re elelor. Majoritatea fiind proaspt absolven i de facultate se ateptau ca nite exper i s vin sa le explice ce software de re ea trebuia de implementat. ns nu a fost aa, cercettorii trebuia s-i dea singuri seama despre ce trebuia realizat. n decembrie 1969 ncepea s func ioneze o re ea experimental ntre UCLA, UCSB, SRI i Universitatea din Utah. Aceste institute aveau mai multe contracte cu ARPA i beneficiau de calculatoare gazd diferite. n trei ani, re eaua s-a extins foarte mult pe teritoriul Statelor Unite. Apoi ARPA a finan at proiecte de cercetare pentru re ele de sateli i i re ele mobile radio cu pachete. n urma unei demonstra ii s-a constatat c protocoalele existente n ARPANET nu puteau fi utilizate de toate re elele. Demonstra ia consta n transmiterea datelor de la un camion care circula n California i folosea re eaua radio cu pachete pentru transmiterea de mesaje ctre SRI, acesta expedia mesajele mai departe pe Coasta de Est, iar prin intermediul sateli ilor mesajele ajungea la University College din Londra. n urma cercetrilor asupra protocoalelor de comunica ie s-a elaborat modelul TCP/IP. Acesta era necesar datorit dezvoltrii exponen iale a ARPANET ului. ARPA dorea adoptarea acestor protocoale i prin urmare a mai ncheiat contracte cu BBN i cu University of California din Berkley pentru integrarea protocoalelor n Berkley UNIX. Cercettorii de la Universitatea din Berkley au dezvoltat interfa a de programare bazat pe socket uri (care este ntlnit i astzi n sistemele de operare din familia Unix), precum i multe aplica ii, utilitare i unelte de administrare care s simplifice interconectarea re elelor. La finalul anilor 1970, Funda ia Na ional de tiin din SUA (National Science Foundation - NSF) a realizat ct de important este re eaua ARPANET pentru dezvoltarea cercetrii din universit ile americane. Re eaua permitea o mai bun colaborare ntre cercettori i partajarea datelor. ns nu toate universit ile aveau contracte de cercetare cu Departamentul Aprrii i deci nu puteau s se lege la ARPANET. De aceea, NSF a creat re eaua CSNET. Apoi organiza iile comerciale erau interesate de legarea la re ea. ns nu se puteau lega la ARPANET, i nici la CSNET ntruct NSF interzicea acest lucru. Totui NSF a ncurajat MERIT, MCI i IBM s formeze o corpora ie non-profit, 5

iar aceasta s-a numit Re ele i Sercivii avansate (Advanced Networks and Services - ANS). Prin anii 1980 a fost creat DNS (Domain Naming System) care organizeaz calculatoarele n domenii i realizeaz coresponden a dintre numele gazdelor i adrese IP. DNS a aprut datorit necesit ii de realizare a unei identificri facile de ctre utilizatorii umani a calculatoarelor din ARPANET. Re eaua devenise imens i era imposibil pentru utilizatori s in minte adresele IP. De la 1 ianuarie 1983, TCP/IP a devenit unicul protocol oficial pentru utilizat n interconectare. Acest lucru a condus la accelerarea creterii numrului de calculatoare conectate la ARPANET. n 1983 ARPA ncredin eaz spre administrare re eaua Agen iei de Comunica ii a Aprrii (Defence Communications Agency - DCA). Primul lucru realizat de DCA a fost separarea re elei militare, astfel rezultnd MILNET. ncepnd cu anul 1984 NSF a construit legturi de mare vitez ntre centrele sale din San Diego, Boulder, Champaign, Pittsburgh, Ithaca i Princeton. Astfel s-a creat un schelet de mare vitez, la care s-au legat toate re elele finan ate de NFS. Astfel s-a format NSFNET care lega mii de universit i, laboratoare de cercetare, biblioteci i muzee. Pe la mijlocul anilor 1980, colec ia de re ele interconectate a fost vzut ca internet, iar apoi ca Internet. n anul 1990, ANS a preluat NSFNET, a modernizat-o i a denumit-o ANSNET. La sfritul anului 1991, Re eaua de Cercetare i Educa ie Na ional din SUA (National Research and Educational Network - NREN) a fost nfiin at printr-un proiect de lege elaborat de Congresul Statelor Unite. NREN stabilea o re ea na ional pentru cercetare i educa ie. n 1995, America Online a cumprat ANSNET. Pentru Europa coloana vertebral pentru organiza iile de cercetare o reprezint re eaua EBONE, iar pentru cele comerciale EuropaNET. Ambele re ele cuprind foarte multe orae din ntreaga Europ.

Serviciile Internetului

Internetul, aceast re ea mondial de re ele de calculatoare, tinde s devin un element foarte important din via a fiecrui om de pe planet. Acest lucru se datoreaz pe de-o parte scderea continu a pre urilor mainilor de calcul i a echipamentelor aferente, ct i a aplorii pe care a cptat-o Internetul. n ziua de azi gsim foarte multe informa ii prin intermediul Internetului, putem comunica foarte uor cu persoane aflate la distan e geografice mari, dar cu care mprtim aceleai preocupri i/sau idei. Ini ial Internet-ul a avut patru servicii principale: 1. Pota electronic. Presupune posibilitatea de a compune, trimite i a recep iona mesaje n format electronic. 2. tiri. Grupurile de tiri reprezint forumuri specializate pe o anumit tem (interes comun), n care fiecare participant poate realiza trimiteri de mesaje ctre ceilal i. Aceste mesaje sunt stocate pentru a fi disponibile i noilor membri. 3. Conectare la distan . Utiliznd telnet sau tehnologii nrudite, orice utilizator se poate conecta la orice gazd din Internet la care are deschis un cont. Conectarea are loc n urma autentificrii utilizatorului. 4. Transfer de fiiere. Prin intermediul protocolului FTP (File Transfer Protocol) se pot realiza transfer de fiiere de la o main de calcul la alta. Apari ia World Wide Web-ului (WWW) a adus un aport foarte important la dezvoltarea Internetului, ntruct permite utilizarea mult mai facil a serviciilor existente.

II. No iuni primare

O re ea de calculatoare reprezint o colec ie de calculatoare autonome interconectate. Dou calculatoare sunt considerate interconectate dac pot realiza schimb de informa ii ntre ele. Un calculator este autonom dac func ionarea acestuia nu poate fi influen at de un altul. Orice calculator care face parte dintr-o re ea de calculatoare este numit nod sau gazd (eng., host). ntr-o re ea pot exista calculatoare specializate care s se ocupe de dirijarea mesajelor ctre mai multe canale de comunica ie. Acestea poart denumirea de ruter (ntruct se ocup cu rutarea pachetelor). Pentru a putea comunica ntre ele calculatoarele trebuie s respecte un anumit set de reguli, adic un protocol. n general pentru comunicare sunt utilizate protocoale, de exemplu n discu ia dintre dou sau mai multe persoane de regul o singur persoan vorbete la un moment dat.

Adrese IP

Fiecare calculator din Internet are o adres IP. Aceasta cuprinde un identificator al re elei din care face parte calculatorul i un identificator pentru identificarea gazdei n cadrul re elei. Adresele IP au 32 bi i lungime i sunt utilizate de protocolul IP pentru stabilirea expeditorului, respectiv a destinatarului unui pachet. Pentru scrierea unei adrese IP se folosete nota ia zecimal cu punct. Fiecare octet este scris n zecimal (deci cu valori cuprinse ntre 0 i 255), iar valorile sunt delimitate prin simbolul punct. Exemple de adrese IP: 193.231.30.197, 10.120.232.15. Exist cinci clase de adrese IP, notate cu A, B, C, D i E. Pentru clasa A primul bit este 0, urmntorii 7 sunt pentru identificarea re elei, iar restul de 24 pentru gazd. Pentru clasa B primii doi bi i sunt 10, urmtorii 14 sunt pentru re ea, iar ultimii 16 pentru gazd. Pentru clasa C primii trei bi i sunt 110, urmtorii 21 pentru re ea, iar ultimii 8 pentru gazd. Pentru clasa D primii bi i sunt 1110, iar pentru clasa E sunt 11110. Clasa D este utilizat pentru multicast, iar clasa E este rezervat pentru utilizrii viitoare. Valoarea zero (0.0.0.0) reprezint gazda sau re eaua curent iar -1 (255.255.255.255) este folosit ca o adres de difuzare pentru toate gazdele din re eaua local. Adresele IP cu valoarea exact pentru re ea i cu to i bi ii 1 pentru gazd pot fi utilizate pentru difuzare de la distan ctre toate gazdele din re eaua specificat. Pachetele trimise ctre adresele de loopback (au forma 127.x.y.z) nu sunt trimise n re ea, n schimb sunt prelucrate local ca i cum ar fi provenit din re ea.

Clasificarea re elelor de calculatoare

Exist mai multe criterii dup care putem clasifica re elele de calculatoare. Dup tipul tehnologiilor utilizate n transmisia datelor re elele de calculatoare se clasific n: a) Re ele cu difuzare. Acestea posed un singur canal de comunica ie partajat de toate calculatoarele din re ea. Atunci cnd un calculator trimite un mesaj unui altuia prin intermediul re elei, mesajul va fi trimis tuturor nodurilor. Fiecare va cerceta la recep ionare dac respectivul mesaj i este destinat. n caz afirmativ con inutul mesajului este citit, altfel este ignorat. Exist i posibilitatea ca un mesaj s fie trimis tuturor calculatoarelor din re ea (eng., broadcast) sau unui grup de calculatoare (eng., multicast). b) Re ele punct-la-punct (point-to-point). Un calculator dintr-o astfel de re ea trimite pachetul doar ctre calculatorul destina ie, eventual folosind noduri intermediare. Pot exista mai multe drumuri dintre expeditor i destinatar, iar alegerea acestuia se realizeaz cu ajutorul algoritmilor de rutare. n general, re elele mai mici utilizeaz difuzarea de mesaje, iar cele de dimensiuni mai mari sunt de tip punct-la-punct. Re elele cu difuzare pot fi la rndul lor mpr ite dup modul de alocare a canalului de comunica ie n statice i dinamice. Un caz de alocare static const n folosirea de intervale de timp n care o gazd poate emite mesaje. Astfel fiecare trebuie s-i atepte rndul. ns dac un calculator nu are ce pachete s trimit atunci cnd i sosete rndul, se irosete timpul alocat acestuia. De aceea n practic sunt utilizate preponderent alocrile dinamice (la cerere) ale canalului de comunica ie. Metodele de alocare dinamic pot fi centralizare sau descentralizate. n cazul centralizat exist o entitate care stabilete dup un anumit algoritm care nod

10

poate transmite date n re ea. Pentru cazul descentralizat, fiecare nod va trebui s stabileasc cnd va transmite pachetele n re ea.

Dup ntinderea geografic pe care o acoper, re ele de calculatoare se mpart n: 1. Re ele locale - LAN (Local Area Network). Acestea se ntind ntr-un birou, o cldire, sau n cteva cldiri apropiate i sunt de dimensiuni restrnse. Spre exemplu, acestea se ntlnesc n cadrul organiza iilor i sunt utilizate pentru partajarea informa iilor i a diverselor dispozitive (imprimante, scannere etc.) 2. Re ele metropolitane - MAN (Metropolitan Area Network) se ntind de regul pe suprafa a unui ora. 3. Re ele larg rspndite - WAN (Wide Area Network) acoper o suprafa geografic mare, de exemplu o ar sau un continent.

Un alt criteriu de clasificare a re elelor de calculatoare l constituie topologia re elei. Astfel putem avea urmtoarele topologii: A. Stea - exist un nod central de care sunt legate celelalte noduri. Dac nodul central se defecteaz atunci ntreaga re ea nu mai este func ional, n schimb dac se defecteaz alt nod sau o legtur, doar un singur nod este afectat de defec iune.

11

B. Inel - fiecare nod este legat de dou noduri nvecinate, formnd o structur de inel (cerc). Defectarea unui nod sau a unei legturi nu pericliteaz buna func ionare a re elei.

C. Arbore - nodurile re elei sunt legate astfel nct nu se formeaz circuite. Defectarea unui nod sau a unei legturi poate conduce la separarea unei subre ele.

D. Complet - fiecare nod din re ea este legat direct cu oricare alt nod din re ea. Avantajul este c defectarea unui nod sau a unei legturi nu afecteaz restul re elei. ns este costisitor pentru a realiza o astfel de topologie de re ea.

12

E. Inele intersectate - reprezint un caz aparte, format din dou inele care au un nod comun. Evident, defectarea nodului comun conduce la separarea celor dou inele.

F. Neregulat - re eaua nu formeaz o topologie anume. Este cea mai ntlnit topologie.

De cele mai multe ori ntlnim re ele de calculatoare cu topologii neregulate.

13

Pentru re elele locale cu difuzare sunt posibile mai multe topologii. ntr-o re ea cu magistral (eng., bus) nu se poate ca dou calculatoare s emit simultan mesaje. Cnd dou gazde doresc s transmit pachete este nevoie de un mecanism de arbitrare care s aleag care dintre cele dou s aib prioritate. Acest mecanism poate fi centralizat sau descentralizat. Un alt caz de re ea cu difuzare l constituie topologia inel. Un caz de arbitrare este cel cu jetonul (folosit n re elele token-ring de la IBM). n inel circul un unic jeton. Dac un nod primete jetonul atunci poate s expedieze mesajele, dup care paseaz jetonul urmtorului nod din cerc.

14

III. Modelul TCP/IP

Modelul TCP/IP este cel mai utilizat model pentru comunicarea dintre calculatoare. Denumirea sa provine de la cele dou protocoale fundamentale utilizate: TCP (Transmission Control Protocol) i IP (Internet Protocol). Ca i alte modele, modelul TCP/IP este construit pe niveluri. Fiecare nivel se bazeaz pe cel aflat sub acesta i ofer servicii pentru nivelul superior. Nivelul n de pe o main comunic cu nivelul n de pe cealalt main. Regulile i conven iile utilizate n comunicarea ntre niveluri constituie un protocol pentru respectivul nivel. Comunicarea dintre nivelul k dintre dou maini nu are loc direct, ci prin intermediul straturilor inferioare. Dac se dorete comunicarea pentru nivelul k ntre mainile A i B, n maina A nivelul k folosete serviciile nivelului k-1, practic mesajul este trimis acestuia, apoi circul mai departe pn la nivelul 1, apoi este trimis fizic prin cablu sau eter, ajunge la maina B la nivelul 1 i este trimis ctre nivelurile superioare pn ajunge la nivelul k. Cnd mesajul este trimis la un nivel inferior, acesta poate aduga la rndul lui informa ii specifice nivelului (protocolului), eventual s mpart mesajul n pachete mai mici pentru a putea fi trimis nivelului inferior sau prin re ea. ntre dou niveluri adiacente exist o interfa . Aceasta definete opera iile i serviciile primitive care sunt oferite de nivelul de jos celui aflat deasupra. O mul ime de niveluri i protocoale alctuiesc o arhitectur de re ea. O list de protocoale utilizate de ctre un anumit sistem, mcar cte un protocol pentru fiecare nivel, se numete stiv de protocoale. Nivelurile modelului TCP/IP sunt: 1. Nivelul gazd-la-re ea (host to network) 2. Nivelul re ea 3. Nivelul transport 15

4. Nivelul aplica ie n continuare vom prezenta succint fiecare nivel i protocoalele aferente fiecruia.

16

Nivelul gazd-la-re ea

Acest nivel face legtura dintre canalul fizic de transmitere a informa iilor i nivelul re ea. Modelul de referin TCP/IP nu prezint n documenta iile sale prea multe informa ii despre acest nivel i protocolul utilizat pentru transmiterea efectiv a pachetelor n re ea. La acest nivel gsim dou protocoale pentru rezolu ia adresei IP: ARP (Address Resolution Protocol) i RARP (Reverse Address Resolution Protocol). Acestea au rolul de a ob ine adresa fizic (adresa Ethernet, sau adresa MAC) corespunztoare unei adrese IP i respectiv invers, pornind de la adresa Ethernet s ob inem adresa IP. Cu adresele IP lucreaz operatorii umani, iar la nivel de main se lucreaz cu adrese Ethernet. Fiecare plac de re ea are o adres unic.

17

Nivelul re ea

Rolul acestui nivel este de a emite pachete n orice re ea i de a face ca pachetele s circule independent pn la destina ie. Eventual pot exista mai multe rute ntre dou gazde. Acest nivel definete clar un format de pachet i un protocol denumit IP (Internet Protocol). Acesta a fost de la nceput proiectat pentru interconectarea re elelor de calculatoare i s-a inut cont de cerin ele ini iale care a condus la apari ia ARPANET-ului: de a nu ntrerupe conexiunile existente i de a gsi rute alternative pentru pachete n cazul defectrii anumitor linii de transmisie sau noduri de legtur. Nivelul re ea se ocup de dirijarea pachetelor n re ea utiliznd diveri algoritmi pentru realizarea acestui lucru precum i de controlul congestiei.

18

Nivelul transport

Nivelul de transport permite realizarea de comunicri de la un capt la altul (end-to-end). Acest nivel cuprinde dou protocoale: TCP (Transmission Control Protocol) i UDP (User Datagram Protocol) pe care le prezentm n continuare separat.

TCP (Transmission Control Protocol)


Protocolul TCP este un protocol sigur orientat conexiune care permite trimiterea unui flux de octe i de la o main la alta fr erori. Protocolul este sigur ntruct nu au loc pierderi de informa ii. Pentru fiecare pachet IP trimis se ateapt o confirmare de primire. Dac aceasta nu apare ntr-un anumit interval de timp, pachetul este retransmis. Mai mult, la recep ionare se verific integritatea datelor, n cazul n care datele au fost alterate se cere retransmiterea mesajului. Pachetele IP pot ajunge la destina ie urmnd drumuri diferite, iar unele pachete pot ajunge naintea altora. De exemplu, ultimul pachet emis poate fi antepenultimul recep ionat. Protocolul TCP reface secven a n care au fost emise pachetele. Protocolul TCP este orientat conexiune, acest lucru nseamn c ambii parteneri care efectueaz comunicarea trebuie s fie disponibili simultan. Este similar cu convorbirile telefonice, cnd ambele persoane implicate trebuie s fie disponibile pentru comunicare.

19

UDP (User Datagram Protocol)


Fa de TCP, protocolul UDP este nesigur, fr conexiune i nu asigur secven ierea pachetelor. Protocolul UDP nu mai gestioneaz numrul de secven pentru pachete, de aceea nu poate reface secven a n care au fost emise pachetele. Tot din aceeai cauz nu poate determina dac un pachet s-a pierdut. n schimb rata de pierdere a pachetelor este foarte mic. Fiind un protocol neorientat conexiune, nu trebuie ca cei doi parteneri de comunicare s fie disponibili simultan. Sistemul este similar cu cel de pot obinuit. Pentru ca A s comunice cu B, A scrie un mesaj (scrisoare) i l expediaz, timp n care nu este solicitat B, apoi mesajul ajunge la B (B nu este obligat ca n acel moment s citeasc pachetul), la un moment dat B citete mesajul i trimite napoi rspunsul, timp n care nu este solicitat A. ntruct nu mai are loc verificarea secven elor i reordonarea pachetelor, se ctig timp, transmisia de date prin intermediul protocolului UDP fiind mai rapid, ns cu riscul de a pierde pachete i de a primi n alt ordine dect cea n care au fost emise.

20

Nivelul aplica ie

Aflat peste nivelul de transport, nivelul aplica ie con ine toate protocoalele de nivel nalt. Ini ial acesta includea protocoalele: Telnet (pentru termial virtual), FTP (pentru transfer de fiiere) i SMTP (pentru pota electronic). Apoi au fost adugate i alte protocoale, cum ar fi protocolul DNS pentru stabilirea coresponden ei dintre numele unei gazde i adresa IP, NNTP utilizat pentru servicii de tiri i HTTP pentru pagini Web.

21

IV. Comenzi pentru re ele de calculatoare

Sistemele de operare actuale ofer o serie de instrumente pentru observarea parametrilor unei re ele sau a conexiunilor acesteia.

Comanda ping
Cu ajutorul comenzii ping se poate determina dac o gazd este accesibil, viteza de transmitere a datelor i rata de pierdere a pachetelor. Ca parametru la linia de comand se d numele gazdei sau adresa IP a acesteia. De exemplu, dac scrim la linia de comand (n Windows sau Unix):
ping 193.231.30.131

Vom ob ine un rezultat de genul:


PING 193.231.30.131 (193.231.30.131) 56(84) bytes of data. 64 bytes from 193.231.30.131: icmp_seq=1 ttl=64 time=0.072 ms 64 bytes from 193.231.30.131: icmp_seq=2 ttl=64 time=0.049 ms 64 bytes from 193.231.30.131: icmp_seq=3 ttl=64 time=0.036 ms 64 bytes from 193.231.30.131: icmp_seq=4 ttl=64 time=0.038 ms 64 bytes from 193.231.30.131: icmp_seq=5 ttl=64 time=0.042 ms 64 bytes from 193.231.30.131: icmp_seq=6 ttl=64 time=0.047 ms 64 bytes from 193.231.30.131: icmp_seq=7 ttl=64 time=0.063 ms 64 bytes from 193.231.30.131: icmp_seq=8 ttl=64 time=0.042 ms 64 bytes from 193.231.30.131: icmp_seq=9 ttl=64 time=0.032 ms 64 bytes from 193.231.30.131: icmp_seq=10 ttl=64 time=0.038 ms --- 193.231.30.131 ping statistics --10 packets transmitted, 10 received, 0% packet loss, time 8999ms rtt min/avg/max/mdev = 0.032/0.045/0.072/0.015 ms

22

Comanda a fost lansat dintr-un sistem Unix i pentru terminarea trimiterii pachetelor se folosete combina ia de taste CTRL+C. Pentru sistemul de operare Window se emit 4 pachete. Pentru a trimite mai multe pachete, pn la apsarea combina iei de taste CTRL+C se va utiliza op iunea -t. n sistemul de operare Windows am rulat comanda ping astfel:
ping mail.yahoo.com

Rezultatul ob inut a fost:


Pinging login.yahoo.akadns.net [209.191.92.114] with 32 bytes of data: Reply Reply Reply Reply from from from from 209.191.92.114: 209.191.92.114: 209.191.92.114: 209.191.92.114: bytes=32 bytes=32 bytes=32 bytes=32 time=163ms time=160ms time=161ms time=160ms TTL=50 TTL=50 TTL=50 TTL=50

Ping statistics for 209.191.92.114: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 160ms, Maximum = 163ms, Average = 161ms

Observm c n ambele cazuri, la final s-au oferit statistici privitoare la timpul de rspuns, numrul de pachete trimise i respectiv recep ionate, rata de pierdere (eng., loss) timpii minim, maxim i mediu de rspuns.

Comanda traceroute
Comanda traceroute (pentru Windows este tracert) afieaz nodurile intermediare pn la gazda specificat i timpii de rspuns pentru fiecare n parte. Ca parametru trebuie s-i furnizm adresa IP sau numele unei gazde din Internet La rularea comentii de mai jos
traceroute www.google.com

23

am ob inut:
traceroute to www.google.com (72.14.221.99), 30 hops max, 40 byte packets 1 193.231.30.190 0.232 ms 0.163 ms 0.229 ms 2 217.73.168.1 0.864 ms 0.898 ms 0.981 ms 3 core.iasi.roedu.net (192.129.4.97) 1.151 ms 0.909 ms 0.781 ms 4 r-gsr12406-pos3-1-155M.nextgen.roedu.net (217.73.160.69) 7.772 ms 8.122 ms 7.845 ms 5 217.73.160.206 7.773 ms 7.607 ms 7.954 ms 6 roedunet2.rt1.bud.hu.geant2.net (62.40.124.245) 23.428 ms 23.185 ms 23.155 ms 7 bpt-b2-pos10-0.telia.net (213.248.103.61) 23.154 ms 22.992 ms 23.260 ms 8 hbg-bb1-pos7-2-2.telia.net (213.248.64.17) 42.947 ms 43.415 ms 43.528 ms 9 hbg-b2-link.telia.net (80.91.249.198) 42.989 ms 43.129 ms 43.638 ms 10 google-110073-hbg-b2.c.telia.net (213.248.96.102) 43.229 ms 42.970 ms 43.450 ms 11 66.249.95.105 54.462 ms 54.413 ms 54.247 ms 12 72.14.232.201 55.081 ms 72.14.232.203 55.322 ms 55.109 ms 13 72.14.232.190 64.717 ms 62.723 ms 72.14.232.194 64.914 ms 14 72.14.221.99 54.650 ms 54.542 ms 55.399 ms

Astfel pn la adresa specificat au fost 13 gazde intermediare, ultima fiind destina ia. Dac gazda are stabilit un nume acesta va fi afiat nso it i de adresa IP. n caz contrar va fi afiat doar adresa IP. Nu toate nodurile permit trecerea tuturor pachetelor. O parte din ele sunt distruse din motive de securitate. n acest caz n loc de numele unei gazde vor apare simbolul asterix de trei ori. Acest lucru se ntmpl i cnd conexiunea de la ultimul nod n colo este defunc ional.

Comanda host
Comanda host permite ob inerea pentru o gazd specificat prin nume sau adres IP aflarea tuturor adreselor IP utilizate, a numelui i a aliasurilor. Exist situa ii cnd pentru un IP avem un nume, cum este cazul prezentat imediat mai jos. Am scris la linia de comand:
host 193.231.30.197

i am ob inut:

24

197.30.231.193.in-addr.arpa domain name pointer fenrir.info.uaic.ro.

n schimb pentru www.microsoft.com am ob inut:


www.microsoft.com is an alias for toggle.www.ms.akadns.net. toggle.www.ms.akadns.net is an alias for g.www.ms.akadns.net. g.www.ms.akadns.net is an alias for lb1.www.ms.akadns.net. lb1.www.ms.akadns.net has address 207.46.20.30 lb1.www.ms.akadns.net has address 207.46.20.60 lb1.www.ms.akadns.net has address 207.46.198.30 lb1.www.ms.akadns.net has address 207.46.198.60 lb1.www.ms.akadns.net has address 207.46.225.60 lb1.www.ms.akadns.net has address 207.46.18.30 lb1.www.ms.akadns.net has address 207.46.19.30 lb1.www.ms.akadns.net has address 207.46.19.60

Observm c n acest caz avem trei aliasuri i opt adrese IP.

25

V. Programarea re elelor de calculatoare

Am ales pentru partea de programare a re elelor de calculatoare limbajul C, n mediul Unix, ntruct permite lucru la un nivel ct mai sczut, ceea ce ne ofer o privire mai detaliat asupra etapelor care sunt parcurse la comunicarea ntre aplica iile de re ea. Limbajele de nivel nalt ascund programatorului aceste detalii, acesta urmnd a utiliza o clas predefinit pentru care detaliile de implementare nu i sunt accesibile n mod direct. Pentru editarea surselor programelor se pot utiliza diverse editoare de texte, cum ar fi joe, pico, mcedit, vim. Compilarea programelor se realizeaz cu compilatorul gcc (GNU C Compiler). Pentru a putea realiza comunicarea ntre dou aplica ii de pe maini diferite mai nti trebuie s crem dou capete de comunicare, cte unul pentru fiecare aplica ie. Aplica iile pot rula i pe aceeai main de calcul, ns acest caz nu prezint interes, eventual doar pentru testare. Capetele de comunicare se realizeaz prin intermediul primitivei select(). Aceasta permite ob inerea unui descriptor, similar cu cel utilizat pentru fiiere i pipe uri. Prin intermediul acestui descriptor vom putea realiza diverse opera iuni, pe care le vom prezenta n acest capitol. Prototipul func iei socket() este urmtorul:
int socket(int domain, int type, int protocol);

Valoarea returnat reprezint descriptorul asociat resursei (captul de comunicare) n caz de succes, iar n caz de eroare se va ob ine -1, iar variabila errno va fi setat corespunztor erorii survenite. Parametrul domain stabilete un domeniul de comunicare, adic familia de protocoale care va fi utilizat. Aceste domenii sunt definite n fiierul header sys/socket.h i se pot utiliza constantele: PF_UNIX, PF_LOCAL pentru comunica ii locale 26

PF_INET pentru protocoalele utilizate n Internet care folosesc protocolul IPv4. PF_INET6 pentru protocoalele utilizate n Internet care folosesc protocolul IPv6. PF_IPX pentru protocoalele Novell IPX. PF_NETLINK pentru protocoale de comunicare ntre kernel i spa iul proceselor utilizator. PF_X25 pentru protocoale ITU-T X.25 / ISO-8208. PF_AX25 pentru protocoale radio AX.25. PF_ATMPVC pentru protocoale ATM PVC. PF_APPLETALK pentru Appletalk. PF_PACKET pentru protocoale de niv jos, bazate pe pachete. n programele nostre vom utiliza frecvent domeniu pentru protocoale Internet IPv4, adic PF_INET. Parametru type indic modul de comunicare: flux de octe i, datagrame etc. i pentru acest parametru avem o serie de constante pe care le putem utiliza. Acestea sunt: SOCK_STREAM pentru comunicare bazat pe flux de octe i (orientat conexiune). SOCK_DGRAM pentru comunicare prin datagrame, cu posibile pierderi de pachete. SOCK_SEQPACKET pentru comunicare bazat pe flux de pachete (orientat conexiune); atunci cnd se va citi va trebui s se citeasc cte un pachet ntreg. SOCK_RAW pentru comunicare prin protocoale de nivel jos. SOCK_RDM pentru comunicare prin datagrame, fr pierdere de pachete. Cele mai utilizarte n practic sunt comunicarea orientat conexiune prin flux de octe i (SOCK_STREAM) i cea neorientat conexiune prin datagrame (SOCK_DGRAM).

27

Utimul parametru stabilete protocolul de comunica ie utilizat. Prezentm mai jos cteva constante care pot fi utilizate pentru parametrul protocol: IPPROTO_TCP IPPROTO_UDP IPPROTO_IP IPPROTO_IPV6 IPPROTO_ICMP IPPROTO_ICMPV6 IPPROTO_IGMP Dac utilizm valoarea zero pentru parametrul protocol, atunci se va alege protocolul care se potrivete cu domeniul i tipul de comunicare. De exemplu, pentru PF_INET i SOCK_STREAM se va alege IPPROTO_TCP, iar pentru PF_INET i SOCK_DGRAM se va alege IPPROTO_UDP. Pentru o mai bun claritate se poate utiliza constantele. Dup ce am creat captul de comunicare va trebui s l atam unei adrese i unui port. Acest lucru se realizeaz prin intermediul primitivei bind(). Aceasta are urmtoarea signatur:
int bind(int sockfd, const struct sockaddr * my_addr, socklen_t addrlen);

Parametrul sockfd reprezint descriptorul de socket care vrem s-l atam, my_addr este o structur care con in datele despre adresa i portul la care se leag socketul, iar addrlen reprezint dimensiunea structurii utilizat de parametrul al doilea. Structura sockaddr este generic i este definit astfel:
Struct sockaddr { /* familia de adrese */ unsigned short sa_family; /* adresa utilizata */ char sa_data[14]; }

28

ns pentru Internet se utilizeaz o alt structur, sockaddr_in care este definit n acest fel:
struct sockaddr_in { /* familia de adrese */ short int sin_family; /* portul */ unsigned short int sin_port; /* adresa */ struct in_addr sin_addr; /* 8 octeti neutilizati, au valoarea zero */ unsigned char sin_zero[8]; }

n defini ia structurii sockaddr_in mai apre structura in_addr care are urmtoarea structur:
struct in_addr { unsigned long int s_addr; }

Pentru portabilitate se folosete constanta INADDR_ANY pentru adresa mainii locale. Dac pentru port se utilizeaz valoarea zero, atunci sistemul va alege un port liber. Dac portul este deja ocupat se va nregistra o eroare (Address already in use), iar errno va avea valoarea EADDRINUSE. Ataarea socketului la o adres i un port este obligatorie pentru programele server, pentur ca aplica iile client s tie unde s se conecteze. Pentru programele client, acest pas este facultativ, caz n care sistemul de operare va aloca un port liber pentru adresa local. Descriptorul de socket poate fi nchis cu primitiva close(), la fel ca n cazul descriptorilor de fiier sau de pipe. Aceasta are ca efect nchiderea conexiunii. Primitivele socket() i bind() sunt utilizate att pentru servere (clien i) TCP, ct i pentru UDP.

29

Servere i clien i TCP

Dup ce am creat socketul i l-am ataat la un port, va trebui s pornim activitatea de primire a clien ilor. Mai nti se apeleaz primitiva listen() care va avea ca efect stabilirea lungimii cozii de ateptare i ateptarea clien ilor. Prototipul func iei listen() este:
int listen(int sockfd, int backlog);

Parametrul sockfd este descriptorul de socket pentru care se ncepe ateptarea clien ilor i pentru care se stabilete lungimea cozii de ateptare. Atunci cnd vine un client acesta este pus n coada de ateptare pn cnd i se accept conexiunea. De regul, este utilizat valoarea 5. n caz de succes, listen() va returna valoarea zero, iar n caz de eroare va returna valoarea -1. Pentru acceptarea unei conexiuni cu un client se va apela primitiva accept(). Aceasta are urmtoarea form:
int accept(int sockfd, struct sockaddr * addr, socklen_t *addrlen);

Parametrul sockfd reprezint descriptorul de socket al serverului pentru care se accept o nou conexiune, structura sockaddr este completat cu datele referitoare la client (familia de adrese, adresa clientului i portul utilizat de acesta), iar addrlen este completat cu lungimea structurii sockaddr. Primitiva accept() este blocant, n sensul c procesul curent se blocheaz pn cnd apare un client. n caz de eroare se va returna valoarea -1, iar n caz de succes se va ob ine un nou descriptor (numit i descriptor de serviciu), prin intermediul cruia se vor trimite i recep iona date de la clientul acceptat.

30

ntruct modul de reprezentare a datelor de pe calculatorul gazd poate diferi de modul de reprezentare utilizat n re ea, va trebui s realizm conversii. n biblioteca netinet/in.h se gsesc cteva func ii utile pentru realizarea de conversii: uint32_t htonl(uint32_t hostlong);

Convertete un ntreg fr semn reprezentat pe 4 octe i din formatul pentru gazd n cel pentru re ea (eng., host to network long). uint16_t htons(uint16_t hostshort);

Convertete un ntreg fr semn reprezentat pe 2 octe i din formatul pentru gazd n cel pentru re ea (eng., host to network short). uint32_t ntohl(uint32_t netlong);

Convertete un ntreg fr semn reprezentat pe 4 octe i din formatul pentru re ea n cel pentru gazd (eng., network to host long). uint16_t ntohs(uint16_t netshort);

Convertete un ntreg fr semn reprezentat pe 2 octe i din formatul pentru re ea n cel pentru gazd (eng., network to host short).

Prezentm n continuare con inutul fiierului server-tcp.c care creeaz un server TCP iterativ. Acesta va primi un mesaj de la client i l va trimite napoi.
/* server-tcp.c */ #include #include #include #include #include #include #include #include <sys/types.h> <sys/socket.h> <netinet/in.h> <errno.h> <unistd.h> <stdio.h> <stdlib.h> <signal.h>

31

#define PORT 8001 /* descriptorul pentru socketul serverului */ int sd = -1; /* descriptorul pentru client */ int client = -1; /* functia de tratare a semnalelor pentru inchiderea serverului */ void terminare(int semnal) { /* afisam un mesaj */ printf("\nInchidem serverul.\n"); /* inchidem descriptorii daca acestia sunt utilizati */ if (client > 0) close(client); if (sd > 0) close(sd); /* terminam programul */ exit(0); } int main() { /* declaram variabilele utilizate */ struct sockaddr_in server; struct sockaddr_in from; char mesaj[128]; int lungime, citit; /* tratam semnale */ if (signal(SIGINT, terminare) == SIG_ERR) { perror("Eroarea la tratarea semnalului SIGINT"); return errno; } /* crearea socketului pentru server */

32

sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sd == -1) { perror("Eroare la crearea socketului"); return errno; } /* initializam structurile de date */ bzero(&server, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(PORT); /* atasam socketul */ if (bind(sd, (struct sockaddr *) &server, sizeof(struct sockaddr)) == -1) { perror("Eroare la atasarea socketului"); close(sd); return errno; } /* serverul va incepe ascultarea la portul stabilit */ if (listen(sd, 5) == -1) { perror("Eroare la inceperea ascultarii"); close(sd); return errno; } printf("Asteptam clienti la portul %d\n", PORT); while(1) { bzero(&from, sizeof(from)); lungime = sizeof(from); printf("Asteptam sa vina un client..."); fflush(stdout); /* acceptam un client */ client = accept(sd, (struct sockaddr *) &from, &lungime);

33

printf("\n"); if (client < 0) { perror("Eroare la acceptarea unei noi conexiuni"); continue ; } bzero(mesaj, sizeof(mesaj)); citit = read(client, mesaj, sizeof(mesaj)); if (citit < 0) { perror("Eroare la receptionarea mesajului"); close(client); client = -1; continue ; } if (citit == 0) { printf("Clientul a inchis conexiunea"); close(client); client = -1; continue ; } printf("Am receptionat mesajul '%s'\n", mesaj); /* trimitem mesajul inapoi */ if (write(client, mesaj, citit) <= 0) { perror("Eroare la expedierea mesajului"); close(client); client = -1; continue ; } printf("Am trimis mesajul inapoi\n"); /* inchidem conexiunea cu clientul */ close(client); client = -1; }

34

return 0; }

Compilarea programului se realizeaz cu comanda gcc, astfel:


gcc server-tcp.c -o server-tcp

Pornirea serverului se face lansnd programul:


./server-tcp

ntr-o alt sesiune de lucru vom porni un client generic, cu care putem realiza testarea serverului:
telnet 127.0.0.1 8001

O posibil testare poate fi:


Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. Salut! Salut! Connection closed by foreign host.

Primul mesaj Salut! este scris de utilizator, iar al doilea este cel recep ionat de la server. Dac ne uitm la consola serverului vom vedea urmtoarele:
Asteptam clienti la portul 8001 Asteptam sa vina un client... Am receptionat mesajul 'Salut! ' Am trimis mesajul inapoi Asteptam sa vina un client...

Observm c serverul a recep ionat inclusiv caracterul pentru trecerea la rnd nou i c serverul continu s atepte clien i. Oprirea acestuia se realizeaz prin apsarea combina iei de taste CTRL+C.

35

De regul nti se realizeaz aplica ia server care poate fi testat cu acest client generic, dup care se dezvolt aplica ia client. Pentru conectarea unui client la server se va utiliza primitiva connect() care are urmtoarea form:
int connect(int sockfd, const struct sockaddr * serv_addr, socklen_t addrlen);

Primitiva connect() are rolul de ini iere a conexiunii. Observm c parametrii sunt similari cu cei utiliza i de bind(), numai c se realizeaz o conexiune la serverul a crui date sunt specificate n structura sockaddr. Implicit func ia connect() este blocant. Aceasta se blocheaz pn cnd serverul va accepta conexiunea sau pn cnd timpul de ateptare s-a terminat, caz n care variabila errno va lua valoarea ETIMEDOUT. n caz de succes se va returna valoarea zero, iar n caz de eroarea se va ob ine valoarea -1. O aplca ie client pentru serverul de mai sus este:
#include #include #include #include #include #include #include <sys/types.h> <sys/socket.h> <netinet/in.h> <errno.h> <unistd.h> <stdio.h> <stdlib.h>

#define SERVER "0" #define PORT 8001 int main() { int sd; struct sockaddr_in server; char mesaj[128]; /* cream socketul pentru comunicare */ sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sd == -1) {

36

perror("Eroare la crearea socketului"); return errno; } /* completam structura cu datele serverului */ bzero(&server, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(inet_addr(SERVER)); server.sin_port = htons(PORT); /* stabilim conexiunea cu serverul */ printf("Ne conetam la server..."); fflush(stdout); if (connect(sd, (struct sockaddr *) &server, sizeof(struct sockaddr)) == -1) { printf("\n"); perror("Eroare la stabilirea conexiunii"); close(sd); return errno; } printf("\n"); /* citim un mesaj de la tastatura */ printf("Introduceti mesajul: "); fflush(stdout); bzero(mesaj, sizeof(mesaj)); fgets(mesaj, sizeof(mesaj), stdin); if (write(sd, mesaj, strlen(mesaj))<=0) { perror("Eroare la expedierea mesajului"); close(sd); return errno; } /* citim raspuinsul de la server */ bzero(mesaj, sizeof(mesaj)); if (read(sd, mesaj, sizeof(mesaj)) < 0) { perror("Eroare la receptionarea mesajului"); close(sd); return errno;

37

} printf("Mesajul receptionat este '%s'\n", mesaj); /* inchidem conexiunea cu serverul */ close(sd); return 0; }

O execu ie posibil a aplica iei client poate fi:


Ne conetam la server... Introduceti mesajul: Salutare! Mesajul receptionat este 'Salutare! '

Observm c i n acest caz este trimis i caracterul pentru trecerea la rnd nou.

38

Servere concurente

Am prezentat pn acum un server iterativ datorit simplit ii. ns dac un client stabilete conexiunea cu serverul i nu mai trimite mesajul, serverul nu va putea deservi ceilal i clien i fiind ocupat cu (blocat de) clientul curent. De aceea n practic sunt utilizate doar servere concurente. Pentru a crea un server concurent avem dou op iuni. Prima const n crearea a cte unui nou proces pentru fiecare client, proces care se va ocupa de rezolvarea cererii/cererilor respectivului client. Astfel procesul principal se va ocupa practic de acceptarea conexiunilor i de crearea proceselor copil. Cea de-a doua op iune const n multiplexarea intrrilor i a ieirilor. ntruct opera iile de intrare/ieire sunt blocante, multiplexarea ne premite s tim pentru care intrri/ieiri putem scrie/citi fr a bloca procesul curent. Pentru a crea un nou proces se poate utiliza func ia fork():
pid_t fork(void);

Aceasta returneaz -1 n caz de eroare, iar n caz de succes returneaz 0 pentru procesul copil i pidul procesului copil pentru procesul printe. Practic din acest punct se va rula dou programe. Se va realiza o copie a memoriei pentru procesul copil, deci nu se va partaja aceeai zon de memorie. De asemenea, se realizeaz i duplicarea descriptorilor. Deci, va trebui s nchidem descriptorii care nu vor fi utiliza i pentru eliberarea resurselor neutilizate. Pentru a ob ine un server concurent utiliznd procese noi pentru tratarea cererilor, vom modifica serverul iterativ dup cum urmeaz: 1. bucla while va deveni:
while(1) { bzero(&from, sizeof(from)); lungime = sizeof(from); printf("Asteptam sa vina un client..."); fflush(stdout);

39

/* acceptam un client */ client = accept(sd, (struct sockaddr *) &from, &lungime); printf("\n"); if (client < 0) { perror("Eroare la acceptarea unei noi conexiuni"); continue ; } switch(fork()) { case -1: perror("Eroare la crearea unui nou proces"); close(client); client = -1; break ; case 0: /* procesul copil */ close(sd); tratare_client(); break; default: /* procesul parinte */ close(client); client = -1; } }

2. func ia de tratare a cererii clientului va fi:


/* functia de tratare a clientului */ void tratare_client() { char mesaj[128]; int citit; bzero(mesaj, sizeof(mesaj)); citit = read(client, mesaj, sizeof(mesaj));

40

if (citit < 0) { perror("Eroare la receptionarea mesajului"); close(client); client = -1; exit(errno); } if (citit == 0) { printf("Clientul a inchis conexiunea"); close(client); client = -1; exit(errno) ; } printf("Am receptionat mesajul '%s'\n", mesaj); /* trimitem mesajul inapoi */ if (write(client, mesaj, citit) <= 0) { perror("Eroare la expedierea mesajului"); close(client); client = -1; exit(errno); } printf("Am trimis mesajul inapoi\n"); /* inchidem conexiunea cu clientul */ close(client); client = -1; /* terminam procesul curent */ exit(0); }

3. pentru a nu ob ine procese zombie vom trata semnalul SIGCHLD n main():


if (signal(SIGCHLD, astptare_copil) == SIG_ERR) { perror("Eroarea la tratarea semnalului SIGCHLD"); return errno; }

41

4. iar func ia de tratare a semnalului SIGCHLD va fi:


/* functia de tratare a semnalului SIGCHLD */ void astptare_copil(int semnal) { wait(NULL); }

Putem utiliza fie clientul generic pentru testarea aplica iilor, fie aplica ia client definit mai sus. Vom observa c dup ce se accept un client va apare aproape instantaneu mesajul care anun ateptarea unui nou client. Cealalt variant de realizare a unui server concurent const n utilizarea multiplexrii, mai concret a primitivei select().
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval * timeout);

Tipul fd_set reprezint o mul ime de descriptori. Observm c primitiva select() folosete trei astfel de mul imi readfds, writefds i exceptfds, pentru a verifica citirea neblocant de la descriptorii din readfds, scrierea neblocant ctre descriptorii din writefds, respectiv pentru recep ionarea de date urgente de la descriptorii din exceptfds. Parametrul n va avea valoarea maxim a descriptorilor prezen i n cele trei mul imi plus o unitate. Parametrul timeout va indica un interval de timp maxim care se va atepta pn la terminarea apelului primitivei select(). Dac se va utiliza valoarea NULL, atunci nu se va utiliza limita de timp, iar pentru valoarea 0, select() va returna imediat. Structura timeval este definit astfel:
struct timeval { long tv_sec; long tv_usec; };

/* secunde */ /* microsecunde */

42

Dup terminarea apelului, cele trei mul i vor con ine doar descriptorii pentru care se pot realiza opera ii neblocante. n cazul n care nu prezint interes vreo mul ime, se poate utiliza NULL. Primitiva select() returneaz -1 n caz de eroare, iar n caz de succes numrul de descriptori prezen i n cele trei mul imi la finalul apelului. Pentru realizarea de opera iuni cu mul imile de descriptori se pot utiliza urmtoarele macrouri: FD_CLR(int fd, fd_set * set); Elimin descriptorul fd din mul imea de descriptori set. FD_ISSET(int fd, fd_set * set); Veridic dac descriptorul fd apar ine mul imii set. FD_SET(int fd, fd_set * set); Adaug descriptorul fd n mul imea de descriptori set. FD_ZERO(fd_set * set); Elimin to i descriptorii din mul ime. Se ob ine astfel mul imea vid.

Programul server care trimite mesajul napoi clientului, n varianta cu multiplexare, este:
#include #include #include #include #include #include #include #include #include <sys/types.h> <sys/socket.h> <netinet/in.h> <errno.h> <unistd.h> <stdio.h> <stdlib.h> <signal.h> <sys/select.h>

#define PORT 8001 /* descriptorul pentru socketul serverului */

43

int sd = -1; /* multimea tuturor descriptorilor pentru clienti */ fd_set fds_all; /* valoarea maxima pentru descriptorii clientilor */ int max_fd = 0; /* functia de tratare a semnalelor pentru inchiderea serverului */ void terminare(int semnal) { int fd; /* afisam un mesaj */ printf("\nInchidem serverul.\n"); /* inchidem conexiunile cu clientii */ for (fd = 0; fd <= max_fd; fd++) if (FD_ISSET(fd, &fds_all)) close(fd); /* inchidem serverul */ if (sd > 0) close(sd); /* terminam programul */ exit(0); } int main() { /* declaram variabilele utilizate */ struct sockaddr_in server; struct sockaddr_in from; fd_set fds_read; char mesaj[128]; int lungime, citit; int client, fd; /* tratam semnale */ if (signal(SIGINT, terminare) == SIG_ERR) {

44

perror("Nu pot atasa functia de tratare pentru SIGINT"); return errno; } /* crearea socketului pentru server */ sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sd == -1) { perror("Eroare la crearea socketului"); return errno; } /* initializam structurile de date */ bzero(&server, sizeof(server)); server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(PORT); /* atasam socketul */ if (bind(sd, (struct sockaddr *) &server, sizeof(struct sockaddr)) == -1) { perror("Eroare la atasarea socketului"); close(sd); return errno; } /* serverul va incepe ascultarea la portul stabilit */ if (listen(sd, 5) == -1) { perror("Eroare la inceperea ascultarii"); close(sd); return errno; } printf("Asteptam clienti la portul %d\n", PORT); /* initializam multimea de descriptori */ FD_ZERO(&fds_all); /* adaugam descriptorul socketului serverului */

45

FD_SET(sd, &fds_all); max_fd = sd; while(1) { /* initializam multimea pentru select */ bcopy(&fds_all, &fds_read, sizeof(fds_read)); if (select(max_fd + 1, &fds_read, NULL, NULL, NULL) < 0) { perror("Eroarea la multiplexare"); exit(errno); } if (FD_ISSET(sd, &fds_read)) { bzero(&from, sizeof(from)); lungime = sizeof(from); printf("A venit un client.\n"); fflush(stdout); /* acceptam conexiunea cu un client */ client = accept(sd, (struct sockaddr *) &from, &lungime); if (client < 0) { perror("Eroare la acceptarea unei noi conexiuni"); } else { FD_SET(client, &fds_all); if (client > max_fd) max_fd = client; } FD_CLR(sd, &fds_read); } /* parcurgem multimea descriptorilor */ for (fd = 0; fd <= max_fd; fd++) { /* daca putem citi in siguranta */ if (FD_ISSET(fd, &fds_read)) {

46

/* citim mesajul, il trimitem inapoi si inchidem conexiunea */ bzero(mesaj, sizeof(mesaj)); citit = read(fd, mesaj, sizeof(mesaj)); if (citit < 0) { perror("Eroare la receptionarea mesajului"); close(fd); FD_CLR(fd, &fds_all); continue ; } if (citit == 0) { printf("Clientul a inchis conexiunea"); close(fd); FD_CLR(fd, &fds_all); continue ; } printf("Am receptionat mesajul '%s'\n", mesaj); /* trimitem mesajul inapoi */ if (write(fd, mesaj, citit) <= 0) { perror("Eroare la expedierea mesajului"); close(fd); FD_CLR(fd, &fds_all); continue ; } printf("Am trimis mesajul inapoi\n"); close(fd); FD_CLR(fd, &fds_all); } } } return 0; }

47

Pentru conectarea la server se poate utiliza telnet sau clientul creat n acest capitol. De obicei se folosete varianta cu crearea de procese n cazul n care clien ii nu interac ioneaz ntre ei prin intermediul serverului (e.g. server de FTP, HTTP). Multiplexarea este preferat atunci cnd clien ii interac ioneaz ntre ei (e.g. server de chat).

48

Servere i clien i UDP

Protocolul UDP nefiind orientat conexiune, nseamn c pentru un server UDP nu se va mai utiliza primitivele listen() i accept(). Se va trece direct la recep ionarea sau transmiterea de datagrame. Pentru expedierea i recep ionarea datagramelor se folosesc frecvent primitivele sendto() i respectiv recvfrom(). Prototipul pentru sendto() este
ssize_t sendto(int s, const void * buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);

iar pentru recvfrom():


ssize_t recvfrom(int s, void * buf, size_t len, int flags, struct sockaddr * from, socklen_t * fromlen);

Parametrul s reprezint descriptorul de socket pentru care este trimis, respectiv recep iona mesajul. Parametrul buf indic zona de memorie n care se afl mesajul, respectiv unde va fi stocat. Parametrul len reprezint numrul de octe i care vor fi transmii, respectiv numrul maxim de octe i care vor fi recep iona i. Cele dou primitive pot folosi indicatori speciali prin intermediul parametrului flag. Dac nu se folosesc indicatori se utilizeaz valoarea zero. Se poate utiliza indicatorul MSG_OOB pentru a indica trimiterea, respectiv recep ionarea unui mesaj urgent, caz n care lungimea mesajului transmis va fi 1. Structura utilizat pentru parametrul to va con ine datele destinatarului, iar tolen lungimea structurii utilizate. Structura dat de va fi completat cu

49

datele expeditorului, iar fromlen va fi completat cu lungimea structurii utilizate pentru parametrul from.

Un server UDP care recep ioneaz mesaje i le trimite napoi este urmtorul:
#include #include #include #include <sys/types.h> <sys/socket.h> <netinet/in.h> <errno.h>

#define PORT 8001 #define MESAJ_SIZE 128 int main() { int sd, dim, citit; struct sockaddr_in server; struct sockaddr from; char mesaj[MESAJ_SIZE]; sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sd == -1) { perror("Eroare la crearea sochetului"); return errno; } /* completam datele pentru server */ server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(INADDR_ANY); server.sin_port = htons(PORT); /* atasam socketul */ if (bind(sd, (struct sockaddr *) &server, sizeof(struct sockaddr)) == -1) { perror("Eroare la atasarea socketului"); close(sd); return errno; }

50

/* servim clientii */ while (1) { dim = sizeof(from); printf("Asteptam un mesaj...\n"); /* receptionam un mesaj */ citit = recvfrom(sd, mesaj, sizeof(mesaj), 0, &from, &dim); if (citit < 0) { perror("Eroare la receptionarea unui mesaj"); continue ; } /* trimitem mesajul inapoi */ printf("Trimitem inapoi mesajul...\n"); if (sendto(sd, mesaj, citit, 0, &from, dim) < 0) { perror("Eroare la expedierea mesajului"); continue ; } } return 0; }

Aplica ia client pentru serverul UDP este:


#include #include #include #include #include <sys/types.h> <sys/socket.h> <netinet/in.h> <errno.h> <stdio.h>

#define SERVER "0" #define PORT 8001 #define MESAJ_SIZE 128 int main() { int sd, dim, citit;

51

struct sockaddr_in server; struct sockaddr from; char mesaj[MESAJ_SIZE]; sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sd == -1) { perror("Eroare la crearea sochetului"); return errno; } /* completam datele serverului */ server.sin_family = AF_INET; server.sin_addr.s_addr = htonl(inet_addr(SERVER)); server.sin_port = htons(PORT); dim = sizeof(server); /* citim mesajul de la tastatura */ bzero(mesaj, sizeof(mesaj)); printf("Mesajul pentru server: "); fflush(stdout); fgets(mesaj, sizeof(mesaj), stdin); /* trimitem mesajul */ if (sendto(sd, mesaj, strlen(mesaj), 0, (struct sockaddr *) &server, dim) < 0) { perror("Eroare la expedierea mesajului"); close(sd); return errno; } /* receptionam mesajul */ bzero(mesaj, sizeof(mesaj)); citit = recvfrom(sd, mesaj, sizeof(mesaj), 0, (struct sockaddr *) &server, &dim); if (citit < 0) { perror("Eroare la receptionarea mesajului"); close(sd); return errno; }

52

printf("Mesajul receptionat este: '%s'", mesaj); close(sd); return 0; }

Dei serverul trateaz pe rnd cererile, acesta poate deservi mai mul i clien i. La apelul func iei recvfrom() se blocheaz pn primete un mesaj de la un client oarecare (care a trimis deja mesajul). Observm c serverul lucreaz cu un singur descriptor pentru socket. Acesta este utilizat pentru att pentru trimiterea ct i pentru recep ionarea mesajelor, fa de cazul TCP cnd pentru fiecare client se folosete un socket de serviciu. Serverul poate pune n legtur doi clien i ai si fr crearea de socketuri suplimentare. Dup ce primete cte un mesaj de la fiecare va putea trimite structurile sockaddr completate automat la recep ionarea mesajelor i celorlal i clien i. Acetia vor putea utiliza respectiva structur pentru a trimite direct informa ii. Prin urmare, orice client UDP poate deveni foarte uor i server. Trebuie s inem cont de faptul c protocolul UDP nu asigur recep ionarea mesajelor n aceeai ordine n care au fost trimise i c mesajele se pot pierde (ns rata de pierdere a mesajelor este extrem de mic).

53

Teme de laborator

1) S se gseasc o comand i parametrii acesteia utiliza ie pentru cutarea de fiiere surs C din contul curent. 2) S se determine numrul de utilizatori conecta i. 3) S se scrie un program C care s citeasc parametri dintr-un fiier de configurare. 4) S se scrie un program C care simuleaz nln uirea de comenzi finger -lp | grep Name. Se va crea cte un proces pentru fiecare comand (se va folosi o func ie din familia exec() pentru execu ia unei comenzi), un pipe pentru comunicare ntre procese i redirectarea intrrii i ieirii standard pentru scrierea/citirea automat n/din pipe. 5) S se modifice serverul TCP iterativ dat ca exemplu, astfel nct s trateze simultan maxim 10 clien i. 6) S se modifice serverul TCP concurent dat ca exemplu, astfel nct s ruleze n fundal i s trateze simultan maxim 10 clien i. 7) S se scrie un program care pentru un nume de server determin adresa/adresele IP utilizate de acesta, i reciproc, pentru o adres IP determin numele serverului. 8) S se implementeze un server de chat. 9) S se scrie o aplica ie client/server care realizeaz opera ii de criptare i respectiv decriptare de fiiere text.

54

10) S se implementeze o aplica ie client/server pentru efectuarea de opera ii cu matrici. 11) S se implementeze o aplica ie client/server pentru stocarea i consultarea re etelor gastronomice. Se va da posibilitatea de a cuta re etele dup denumire, categorie, ingrediente.

55

Bibliografie

[1]

S. Buraga, G. Ciobanu, Atelier de programare n re ele de calculatoare, Editura Polirom, Iai, 2001. S.Buraga, V. Tarhon-Onu, . Tanas, Programare Web n bash i Perl, Editura Polirom, 2002. A. Tanenbaum, Re ele de calculatoare, edi ia a treia, Editura Computer Press Agora, Tg. Mure, 1998.

[2]

[3]

56

S-ar putea să vă placă și