Documente Academic
Documente Profesional
Documente Cultură
Ce ste un socket?
Tipuri de socket
Adrese socket
Model de comunicatie client – server
Functii
Completarea structurii sockaddr_in
Exemple
Cerinte pt laborator
Bibiliografie
1
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Ce este socket?
Un socket este un „capat de comunicatie" sau „punct final de comunicatie" care poate fi numit si adresat intr-o retea, fiind locul
unde programul de aplicatie se intalneste cu furnizorul mediului de transport.
Un soket este:
- d.p.d.v. al unui program de aplicatie: o resursa alocata de sistemul de operare;
- d.p.d.v. al sistemului de operare: o structura de date intretinuta de catre nucleul sistemului de operare; aceasta structura este
referita in aplicatii printr-un intreg numit descriptor de socket.
socket-aparat telephonic
- proprietarul formeaza un numar si dupa stabilirea legaturii incepe sa discute cu persoana de la celalalt capat al firului;
- aparatul si intreaga retea telefonica asigura stabilitatea legaturii pana la incheierea convorbirii .
OBS. doua aplicatii pot comunica intre ele prin socket doar dupa ce fiecareia dintre ele sistemul de operare i-a alocat un socket
(exista un numar de descriptori de socket rezervati pentru aplicatiile de sistem, restul descriptorilor fiind disponibili pentru
utilizatori).
2
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Tipuri de socket
Se disting doua tipuri de socket: socket stream si socket datagram. Comunicarea este posibila, doar daca la ambele capete este
utilizat acelasi tip de socket.
Socket stream
Interfata socket stream defineste un serviciu orientat conexiune, datele fiind transmise fara erori si fara duplicari, Datele sunt
receptionate in aceeasi ordine in care au fost transmise, avandu-se grija insa ca fluxul de date sa nu depaseasca o valoare maxima de
octeti la un moment dat. Asupra datelor ce sunt transmise nu se impune nici un fel de limitare, ele fiind considerate simple siruri de
octeti. Transportul este realizat folosind protocolul TCP. Fiind un serviciu orientat conexiune, este potrivita analogia facuta anterior
cu aparatul telefonic. Ca exemplu de utilizare pentru socket stream poate fi dat unul dintre serviciile nivelului aplicatie, si anume FTP
(File Transfer Protocol).
Deci, socket stream asigura o conexiune sigura, lucru care presupune insa reducerea performantei datorita efortului de calcul
necesar mentinerii conexiunii si verificarilor de corectitudine. La nivel utilizator aceasta reducere a performantei nu este insa
sesizata .
Se recomanda utilizarea socket-ului stream in cazurile in care cantitatile de date ce sunt transmise sunt mari, iar comunicatia are loc
in retele WAN.
3
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Socket datagram
Interfata socket datagram defineste un serviciu fara conexiune in care datagramele sunt transmise ca si pachete separate. Serviciul
nu asigura garantii cu privire la receptionarea datelor, acestea putand fi pierdute ori duplicate, ordinea de sosire la destinatie putand
fi de asemenea diferita de cea de transmitere. Marimea unei datagrame este limitata la numarul de octeti care pot fi transmit intr-o
singura tranzactie. Transportul este realizat folosind protocolul UDP, iar analogia potrivita este cea cu cutia postala.
Comunicarea prin socket-ul datagram este nesigura deoarece pachetele pot fi ignorate, alterate sau duplicate in timpul transmisiei,
utilizarea lui fiind recomandata in cazurile in care aplicatia implementeaza un mecanism propriu de corectitudine sau daca aplicatia
nu este sensibila la transmisii eronate. Se castiga insa viteza la prelucrare raportat la socket-ul stream.
Se recomanda folosirea acestui tip de socket pentru transmiterea unei cantitati mici de date in cadrul retelelor LAN.
4
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Adrese socket
Pentru a fi independent de platforma, socket permite utilizarea mai multor familii de adrese, o astfel de familie definind un stil
de adresare. Toate host-urile din aceeasi familie de adrese inteleg si folosesc aceeasi schema pentru adresarea capetelor socket-ului.
Familiile de adrese sunt identificate printr-un numar intreg, numele acestora incepand cu AF (Adress Family):
AF-INET: defineste adresarea in domeniul Internet, fiind si cea mai importanta familie;
5
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Adresele din familia AF_INET sunt de tip struct sockaddr_in si sunt definite in <arpa/inet.h> astfel:
struct in_addr {
union {
struct{
unsigned char s_b1,
s_b2,
s_b3,
s_b4;
} S_un_b;
struct {
unsigned short s_w1,
s_w2;
} S_un_w;
unsigned long s_addr;
} S_un;
};
struct sockaddr_in{
short sin_family; //valoare AF_INET
unsigned short sin_port; //numarul de port
struct in_addr sin_addr; //adresa IP
char sin_zero[8]; //nefolosit
};
6
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Secventa de initializare:
7
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
• socket: cere nucleului sistemului sa creeze un socket prin care sa poata fi contactat; se fixeaza familia de adrese folosita si tipul
de socket (in acest caz stream) ;
• connect: initiaza conexiunea intre aplicatia client si aplicatia server. La finalul acestui apel, fie exista o conexiune stabila intre
client si server, fie se returneaza un cod de eroare.
Apelurile sistem socket si connect trebuie efectuate in mod obligatoriu in aceasta ordine si o singura data. Daca se apeleaza
connect pentru un socket deja conectat se va reurna o eroare.
Apelurile sistem send si recv NU trebuie efectuate in mod obligatoriu in aceasta ordine. Ordinea prezentata in figura corespunde
comunicatiei de tip cerere-raspuns. De asemenea aceste metode se pot apela de mai multe ori. Ordinea apelurilor depinde de modul
in care sunt implementate aplicatiile server si client.
8
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Functia socket
Aceste apeluri sistem trebuie precedate de specificarea fisierului header:
#include <sys/socket.h>
unde:
familie: indica familia de adresa socket utilizata (AF_INET, AF_UNIX, etc);
tip: indica tipul de socket folosit (SOCK_STREAM, SOCK_DGRAM);
protocol: argument care are valoare 0 cu specificatia „lasam sistemului alegerea protocolului"
Apelul creaza un socket care va asigura conectivitatea programului local, fie el client sau server. Apelul intoarce un SOCKET (
intreg), notat in cele ce urmeaza cu sd si care reprezinta descriptorul de socket (folosit de apelurile care urmeaza ca si parametru).
sd se mai numeste si socket(descriptor) de intalnire.
9
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Functia connect
int connect( int sd, struct sockaddr *saddr, int sz);
//returneaza 0 la succes si -1 la eroare
Un proces client care foloseste socket stream solicita nucleului sa conecteze prin sd, serverul avand adresa socket saddr
reprezentata pe sz octeti.
Structura sockaddr este o strucura generica prin intermediul careia se pot seta informatiile de identificare ale unui socket. Pentru
socketul din familia AF_INET informatiile necesare pentru identificare sunt adresa IP si portul. Se poate observa ca structura
sockadrr_in contine aceste campuri. Problema care apare in acest moment este cum se poate transforma o structura de tip sockaddr
intr-o structura de tip sockaddr_in. O solutie ar fi fost folosirea mostenirii. Mai exact, structura sockaddr?in sa mosteneasca stuctura
sockaddr, dar acest lucru nu este posibil datorita faptului ca aceste structuri, ca si metodele despre care am discutat pana acum,
sunt definite intr-un limbaj procedural (limbajul C) in care nu exista notiunea de mostenire. Ne ajuta totusi o alta particularitate a
limbajului C, si anume un pointer se poat converti intr-un alt pointer folisnd un simplu „cast". Astfel, putem crea o structura de tip
sockaddr_in in care sa scriem datele de care avem nevoie, sa obtinem un pointer la aceasta structura si sa convertim acest pointer la
un pointer de tip sockaddr pe care sa il oferim ca parametru metodei connect. Ex.:
SOCKET sd;
struct sockaddr_in saddr;
int sz = sizeof(saddr);
//apelam connect
int result = connect(sd, (struct sockaddr*) &pointer_sockaddr, sz);
In acest fel metoda connect poate fi folosita si pentru alte familii de socket. Este suficient sa definim o noua structura
asemanatoare cu sockaddr care sa contina detaliile de identificare pentru socketul din familia noastra.
10
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Concret, membrul sin_port va primi valoarea portului iar membrul sin_addr adresa IP.
Portul este un numar pe 2 octeti si trebuie specificat in formatul retea (Big Endian).
Pe o masina Big Endian atribuirea se poate face direct deoarece datele au aceiasi reprezentare in memorie. In cazul in care
matina foloseste Little Endian nu se poate face o atribuire directa ci trebuie facuta mai intai o conversie din Little Endian in Big
Endian.
Motivul pentru aceasta conversie este ca daca masina este Little Endian atunci octetul cel mai putin semnificativ este la adresa
cea mai mica iar atunci cand se citeste valoarea in formatul retea acest octet devine cel mai semnificativ
11
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Exemplul de mai sus corspunde situatiei in care masina foloseste o reprezentare Big Endian si s-a facut o atribuire directa intre
valoarea portului si membrul sin_port al structurii sockaddr_in:
12
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Exemplul de mai sus corspunde situatiei in care masina foloseste o reprezentare Little Endian si s-a facut o atribuire directa intre
valoarea portului si membrul sin_port al structurii sockaddr_in:
saddr.sin_port = 43962; // OxABBA in hexazecimal
Sa presupunem ca structura saddr este pastrata in memorie incepand cu adresa 0x0028. Rezulta ca membrul sin_port se va afla
in memorie incepand cu adresa 0x002A. Deoarece reprezentarea este Little Endian atunci octetul cel mai putin semnificativ se va
afla la adresa cea mai mica. Atunci cand valoarea portului se va copia in sirul de octeti ce va fi trimis in retea octetii se copiaza in
aceiasi ordine. Rezulta ca octetul cel mai putin semnificativ al portului se va afla inaintea octetului mai semnificativ (in cazul nostra
LSB este octetul 12 iar MSB este octetul 13).
Atunci cand se va interpreta valoarea in formatul retea se va citi mai intai MSB-ul si din octetul urmator LSB-ul. Rezulta valoarea
OxBAAB (in hexazecimal), o valoare diferita de cea dorita. Pentru a se obtine valoarea dorita este necesara inversare a celor doi
octeti. Astfel, in loc sa facem o atribuire directa a valorii, vom folosii metoda htons. Aceasta metoda face o transformare a unui short
din formatul masinii (in cazul nostru Little Endian) in formatul retea (identic cu Big Endian).
saddr.sin_port = htons(43962);
13
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
In urma apelului htons numarul OxABBA este convertit la numarul OxBAAB si salvat in memorie in formatul Little Endian. Astfel
octetul mai putin semnificativ (OxAB) va fi salvat la adresa mai mica iart octetul cel mai semnificativ (OxBA) la adresa mai mare.
Atunci cand se copiaza valoarea in sirul de octeti transmis in retea se va pastra ordinea din memorie. Insa atunci cand valoarea este
interpretata, se va incepe citirea cu primul octet si aacesta va fi interpretat ca MSB. Rezulta valoarea OxABBA, adica exact valoarea
dorita.
Aceiasi situatie apare si in cazul adresei IP. Adresa IP este un numar de 32 de biti (4 octeti). In cadrul structurii sockaddr_in adresa ip
(membrul sin_addr) este reprezentata ca un union. Un union este asemanatopr cu o structura, diferenta fiind aceea ca in cazul unei
structuri fiecare membru ocupa propria zona de memorie, in timp ce in cazul unui union toti membrii impart aceiasi zona de
memorie (memoria alocata este dimensiunea celui mai mare membra). In cazul nostra acest union contine o structura cu 4 char-uri
(dimensiune 4*1=4), o structura cu 2 short-uri (dimensiune 2*2=4) si un unsigned long (dimensiune 1*4=4). Dimensiunea union-ului
este deci 4. Practic, acest union permite scrierea adresei IP in 3 feluri in aceiasi zona de memorie. La final, in memorie, trebuie sa
apara la adresa cea mai mica cel mai semnificativ octet al adresei IP.
Ex. Daca avem adresa IP 127.0.0.1 se pot folosi urmatoarele variante pentru a seta adresa IP:
A:
saddr.sin_addr.s_un_b.s_b1 = 127;
saddr.sin_addr.s_un_b.s_b2 = 0;
saddr.sin_addr.s_un_b.s_b3 = 0;
saddr.sin_addr.s_un_b.s_b4 = 1;
B:
saddr.sin_addr.s_un_w.s_w1 = htons(16128);
saddr.sin_addr.s_un_w.s_w2 = htons(1);
C:
saddr.sin_addr.s_addr = inet_addr(„127.0.0.1");
Din cele 3 variante ultima este cea mai simpla practic adresa IP se scrie sub forma unui sir de caractere iar metoda inet_addr se
ocupa de conversia ei intr-un numar scris direct in formatul retea.
14
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Functia Bind
int bind ( SOCKET sd, struct sockaddr * saddr, int sz);
//returneaza 0 la succes si -1 la eroare
Server-ul isi inregistreaza adresa socket proprie saddr, pentru socket-ul sd; lungimea adresei local este sz. In
saddr se trece numarul de port la care poate fi contactat, tot in local in campul sin_addr.s_addr se trece adresa IP
a serverului sau constanta INADDR_ANY. Structura sockaddr va fi inlocuita cu o structura sockaddr_in (vezi
metoda connect pentru detalii). Pentru port se foloseste aceiasi valoare ca si pentru connect (trebuie sa fie
acelasi port pentru a se putea stabili conexiunea)
15
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Funtia Listen
int listen (SOCKET sd, int lungcoada);
//returneaza 0 la succes si -1 la eroare
unde:
lungcoada: indica numarul maxim de conexiuni care sunt acceptate pe socket-ul sd in asteptare daca server-ul este ocupat (cele
ce depasesc lungcoada vor fi refuzate); majoritatea sistemelor de operare nu admit mai mult de 5 clienti simultan.
16
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Functia Accept
#include <sys/types.h>
#include <sys/socket.h>
int accept(int sd, struct sockaddr *addr, socklen_t *addrlen);
Apelul pune server-ul sa astepte o conexiune socket stream sd pana cand un client reuseste un connect la el. La realizarea
conexiunii, in argumentele addr si addrlen sunt intoarse adresa socket a clientului si lungimea pe care este reprezentata aceasta.
Apelul intoarce trei valori:
1. un SOCKET pe care il notam fd. Acesta reprezinta un descriptor pe care server-ul il foloseste pe post de descriptor de fisier
pentru schimbul de mesaje cu clientul; fd se mai numeste si socket (descriptor) de schimb.
2. adresa socket a procesului client in departe. Structura oferita ca parametru va fi umpluta automat cu datele clientului
3. lungimea acestei adrese in addrlen.
17
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
unde:
sd: descriptorul de socket prin care se realizeaza comunicatia cu partenerul departat; acest intreg provine dintr-un apel
socket, cu exceptia send si recv dintr-un server socket stream, cand acesta provine din apelul accept;
f: flag care are de regula valoarea 0 lasand in seama sistemului fixarea unor flaguri
Apelul send expediaza prin sd, un numar de maxim n octeti pe care ii ia din memorie incepand cu adresa T.
OBS.
• in cazul send (cazul socket stream) adresa IP si portul destinatarului se stabilesc la conexiune;
• intregul returnat de apel reprezinta numarul de octeti care s-a putut transmite , in caz contrar, se intoarce o valoare negativa.
Apelul recv receptioneaza prin sd un numar de maxim n octeti pe care ii depune in memorie incepand cu adresa T.
Programatorul trebuie sa se asigure ca zona tampon are rezervati la adresa T cel putin n octeti.
OBS.
• in cazul recv (cazul socket stream) adresa IP si portul destinatarului se stabilesc la conexiune;
• intregul returnat de capel reprezinta numarul de octeti care au fost receptionati; faptul ca s-a inchis conexiunea este semnalat
prin intoarcerea valorii 0; in caz de eroare se intoarce o valoare negativa.
OBS. tratarea situatiilor in care nu s-au transmis sau receptionat exact cei n octeti solicitati cade exclusiv in sarcina programatorului.
Daca prin socket se poate transmite fie si numai 1 octet, acesta se va transmite si operatia este considerata incheiata.
18
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Rutina inet_addr transforma sirul de caractere S scris in conventie C si care contine o adresa IP (scrisa in notatia punctuala), intr-
o adresa de 32 biti a carei valoare o intoarce.
Rutina inet_ntoa face operatia inversa, adica transformas intregul lung I intr-un sir de caractere care contine adresa IP in notatia
punctuala.
19
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Internet v6
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
int inet_pton(int af, const char *src, void *dst);
Return Value
inet_ntop() returns the dst parameter on success, or NULL on failure (and errno is set).
inet_pton() returns 1 on success. It returns -1 if there was an error (errno is set), or 0 if the input isn't a valid IP address
20
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Exemple
Exemplu Server
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* portul folosit */
#define PORT 8000
int main ()
{
struct sockaddr_in server; /* structurile folosite de server si client */
struct sockaddr_in from;
char buffer[100]; /* mesajul trimis de client */
int sd; /* descriptorul de socket */
/* cream un socket */
if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
{
perror ("Eroare la socket().\n");
21
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
return errno;
}
/* atasam socketul */
if (bind (sd, (struct sockaddr *) &server, sizeof (struct sockaddr) ) == -1)
{
perror ("Eroare la bind().\n");
return errno;
}
22
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
/* citirea mesajului */
if ((nr = recv (client, buffer, 100, 0)) <= 0)
{
perror ("Eroare la read() de la client.\n");
close (client); /* inchidem conexiunea cu clientul */
continue;
}
23
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
24
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Exemplu Client
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
25
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
/* ne conectam la server */
if (connect (sd, (struct sockaddr *) &server, sizeof (struct sockaddr)) == -1)
{
perror ("Eroare la connect().\n");
return errno;
}
gets(buffer);
nr = strlen(buffer);
if (send (sd, buffer, nr, 0) <= 0)
{
perror ("Eroare la write() spre server.\n");
return errno;
}
/* citirea raspunsului dat de server (asteptam pana cind raspunde serverul)*/
if ( (nr = recv (sd, buffer, 100, 0)) < 0)
{
perror ("Eroare la read() de la server.\n");
return errno;
}
buffer[n] = 0;
printf ("Mesajul primit este: %s\n", buffer);
/* inchidem conexiunea*/
close (sd);
}
26
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Cerinte laborator
Exercitiul 1.
Folosind functiile socket, connect, send, recv si close, scrieti o aplicatie client care trebuie sa indeplineasca urmatoarele cerinte:
• se conecteaza la aplicatia server pe portul 12346 si adresa IP 127.0.0.1
• ii trimite serverului un text (maxim 256 de caractere)
• asteapta de la server un mesaj de maxim 256 de caractere
• inchide conexiunea cu serverul.
Exercitiul 2.
Folosind functiile socket, connect, send, recv si close, scrieti o aplicatie server care trebuie sa indeplineasca urmatoarele cerinte:
• se ataseaza la portul 8080
• primeste mesaje de tip GET in format HTTP/1.1
• raspunde in format HTTP cu un header raspuns
• livreaza fisierul cerut
• mentine conexiunea cu clientul.
Exercitiul 3.
Folosind functiile socket, connect, send, recv si close, scrieti o aplicatie client care trebuie sa indeplineasca urmatoarele cerinte:
• se conecteaza la aplicatia server pe portul 8080 si adresa IP 127.0.0.1
• ii trimite serverului un mesajul GET in format HTTP/1.1
• asteapta de la server un raspuns in format HTTP/1.1
• parseaza si intelege raspunsul, asteapta si receptioneaza daca este cazul un fisier transmis de server
• afiseaza continutul fisrului pe ecran
• inchide conexiunea cu serverul.
27
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Bibliografie suplimentara
A. Tanenbaum, Reţele de calculatoare (ediţia a patra), Byblos, Tg.Mureş, 2003
D. Comer, Internetworking With TCP/IP, vol.I: Principles, Protocols, and Architecture (2nd edition), Prentice Hall, New Jersey, 1991
D. Comer, D. Stevens, Internetworking with TCP/IP: vol.III: Client-Server Programming and Applications, Prentice Hall, New Jersey,
1993
K. Ross, D. Rubenstein, P2P Systems, Tutorial, 2004
S. Raab et al., Mobile IP Technology and Applications, Cisco Press, 2005
J. Doyle, CCIE Professional Development: Routing TCP/IP, Volume I, Macmillan Technical Publishing, 1998
K. Robbins, S. Robbins, UNIX Systems Programming: Communication, Concurrency, and Threads, Prentice Hall PTR, 2003
R. Stevens, TCP/IP Illustrated, Volume 1: The Protocols, Addison-Wesley Longman, 1994 –
R. Stevens, TCP/IP Illustrated, Volume 2: The Implementation, Addison-Wesley Longman, 1995
R. Stevens, TCP/IP Illustrated, Volume 3: TCP for Transaction, HTTP, NNTP, and the UNIX Domain Protocols, Addison-Wesley
Longman, 1996
R. Stevens, B. Fenner, A. Rudoff, UNIX Network Programming Volume 1, Third Edition: The Sockets Networking API, Addison Wesley,
2003
J. Martin, J. Leben, TCP/IP Networking, Prentice Hall, New Jersey, 1994
A. Abbas, Grid Computing: A Practical Guide to Technology and Applications, Charles River Media, 2004
M. Ben-Ari, Principles of Concurrent Programming, Prentice Hall International, 1982
S. Dixit, R. Prasad (eds.), Wireless IP and Building the Mobile Internet, Artech House, 2003
A. Grama et al., Introduction to Parallel Computing (2nd edition), Addison Wesley, 2003
28
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
29
Retele de calculatoare - Introducere in programarea aplicatiilor de retea
Rezumat
Ce ste un socket?
Tipuri de socket
Adrese socket
Model de comunicatie client – server
Functii
Completarea structurii sockaddr_in
Exemple
Cerinte pt laborator
Bibiliografie
Intrebari ?
30