Interfetele de programare a aplicatiilor permit programatorilor sa scrie aplicatii care pot face uz de serviciile TCP/IP. Interfata socket este una dintre dinte cele cateva API-uri catre protocoalale de comunicatie.
In anii '80 Agentia pentru Proiecte de cercetare Avansata (Advanced Research Projects Agency - ARPA) a guvernului SUA a oferit Universitatii Berkeley din statul California fonduri pentru implementarea suitei TCP/IP sub sistemul de operare Unix. Proiectat pentru a fi o interfata generica de programare a comunicatiei, interfata socket a fost pentru prima data introdusa pe sistemul UNIX BSD 4.2. Cu toate ca nu a fost standardizata, aceasta intefata a devenit un standard industrial de facto. Interfata socket este deosebita de serviciile care sunt furnizate aplicatiilor: socketurile pentru streamuri (stream sockets) (orientate pe conexiune), socketurile pentru datagrame (datagram sockets) (fara conexiune), si socketurile raw (raw sockets) (pentru accesul direct la protocoalele din straturile inferioare).
O varianta a interfetei socket a BSD este asigurata de catre interfata Winsock dezvoltata de catre Microsoft si alte companii pentru a suporta aplicatii TCP/IP pe sistemele de operare Windows. Winsock 2.0, ultima versiune, asigura o interfata si mai generalizata permitand aplicatiilor sa comunice cu orice protocol din stratul de transport disponibil si cu serviciile de retea aferente, incluzand dar ne limitandu-se la, TCP/IP. Mai multe detalii vor fi date in sectiunea Winsock V2.0.
O trecerea in revista a acestor functii este data in continuare.
socket. Initializeaza un socket.FORMAT:
SOCKET sockfd = socket(int af, int type, int protocol)
unde:
–
afse refera la familia de adrese (sau familii de protocolale). Acest parametru poate lua valori precum AF_UNIX (pentru Unix), AF_INET (pentru Internat), AF_NS (pentru XNS - Xerox Network Services, inclusiv IPX), AF_IPX (pentru IPX si SPX) si AF_NETBIOS (pentru NeTBIOS) si altele. Scopul sau este de a specifica metoda de adresare utilizata de catre socket. Dupa cum se cunoaste formatul adreselor de retea variaza de la o retea la alta. Pe fiecare tip de retea sunt implementate diferite suite de protocoale (familii de protocoale). Diferenta intre familiile de protocoale si de adrese rezida in aceea ca permite programatorilor sa utilizeze protocoale de retea care contin mai multe reprezentari ale adreselor in cadrul aceleiasi suite de protocoale. Pentru familiile de protocoale, in bibliotecile interfetei socket, sunt definite o serie de constante care incep cu prefixul PF_. Astfel pentru internet se foloseste PF_INET. Constantele PF_INET si AF_INET au aceeasi valoare si de aceea multi le folosesc pe una sau pe cealalta.–
typese refera la tipul interfetei socket care va fi folosit. Acest parametru poate lua valori precum SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, si SOCK_SEQPACKET.
–protocolspecifica protocolul. Protocolul este specificat prin constante al caror nume incep cu prefixul IPPROT_. Spre exemplu, pentru protocoalele UDP, TCP, IP si ICMP se folosesc valorile IPPROTO_UDP, IPPROTO_TCP, IPPROTO_IP si IPPROTO_ICMP.
–sockfdeste un intreg fara semn redefinit caSOCKET(analog unui descriptor de fisier) returnat de catre apelul functieisocket. In caz de eroare valoarea intoarsa este SOCKET_ERROR avand valoarea -1.
bind. Inregistreaza un socket la o adresa de port.FORMAT:
int bind(SOCKET sockfd, const struct sockaddr FAR *localaddr, int addrlen)
Unde:
–
sockfdeste intregul returnat de catre functiasocket.
–localaddreste adresa locala returnata de apelul functieibind.
De retinut ca dupa apelarea functiei bind se obtin valori pentru primii trei
parametrii ai cvintetului (asociatiei):
{protocol, local-address, local-process, foreign-address, foreign-process}
listen. Indica disponibilitatea de a
accepta conectari.FORMAT:
int listen(SOCKET sockfd, int queue_size)
Unde:
–
sockfdeste acelasi intreg returnat de functiasocket.
–queue_sizeindica numarul de cereri de conectare care pot fi puse in lista de asteptare de catre sistem in timp ce procesul local nu a emis apelul accept.
accept. Acceptarea unei conexiuni.FORMAT:
int accept(SOCKET sockfd, struct sockaddr FAR *foreign_address, int addrlen)
unde:
– sockfd este acelasi intreg returnat de functia socket.
– foreign_address este adresa procesului (client) strain returnat
de catre apelul accept.
De notat ca acest apel al functiei accept este emis de catre
procesul server si nu de catre procesul client. Daca exista o cerere de
conectare in coada asteptare la acest socket, accept preia prima
cerere din lista de asteptare si creaza un alt
socket cu aceleasi proprietati ca sockfd; in caz contrar, accept
va bloca procesul pana cand apare o cerere de conectare.
connect. Cerere de conectare la un sever.FORMAT:
int connect(SOCKET sockfd, struct sockaddr *foreign_address, int addrlen)
Unde:
– sockfd este intregul returnat de catre functia socket.
– foreign_address este adresa procesului (server) strain returnat
de apelul connect.
Nota: Acest apel este emis de catre procesul client si nu de catre procesul server.
Apelurile read(), readv(sockfd, char *buffer int addrlen),
recv(), readfrom(),
send(sockfd, msg, len, flags) si write() pot fi folosite
pentru a citi sau scrie date de la/la o conexiune stabilita (asociatie socket).
Nota: Aceste apeluri sunt similare apelurilor standard de citire si scriere a fisierelor.
close. Inchiderea unui socket.FORMAT:
int close(SOCKET sockfd)
Unde:
– sockfd este intregul returnat de catre functia socket.
Figura urmatoare prezinta apelurile tipice pentru socketuri pe care o aplicatie le poate folosi cu un protocol orientat pe conexiune.

Partea din stanga a diagramei reprezinta apelurile de functii facute de server, partea din dreapta reprezinta apelurile de functii ale clientului. Sagetile verticale reprezinta ordinea apelurilor, iar sagetile orizontale fluxul comunicatiei intre cele doua procese.
Pentru implementarea unui server orientat pe conexiune sunt necesare, in ordine, urmatoarele apeluri de functii API.
socket. Serverul creeaza un socket cu functia socket.bind. Serverul inregistreaza (leaga) socketul la un port
local.listen. Functia listen cere socketului sa astepte cereri de
conectare si sa confirme primirea acestora. Functia listen
trece socketul intr-o stare de asteptare pasiva.Un socket care sta in
ascultare va trimite fiecarui solicitant un mesaj de confirmare ca serverul
a receptionat cererea de conectare. Un socket in ascultare nu accepta de
fapt cererea de conectare.accept. Programul server va trebui sa foloseasca pentru
aceasta functia accept.Pentru implementarea unui client orientat pe conexiune sunt necesare, in ordine, urmatoarele apeluri de functii API.
socket. Clientul creeaza de asemenea un socket cu functia socket.connect. Clientul nu este interesat de adresa locala de
protocol si de acea nu foloseste functia bind. In schimb, clientul orientat
pe conexiune initiaza conversatia in retea apeland functia connect.Dupa ce serverul si clientul stabilesc conexiunea, comunicatia care urmeaza
are loc prin intermediul functiilor read si write de
ambele parti. Totusi, clientul si serverul mai pot utiliza functiile send
si recv sau orice alte functii care lucreaza cu socketuri conectate
(precum sendto
si recvfrom).
Figura urmatoare ilustreaza secventa tipica de apelurile pentru socketuri utilizate la protocoale fara conexiune.

Programul server fara conexiune din figura de mai sus utilizeaza apelurile socket
si bind in acelasi mod in care o face si un server orientat pe
conexiune. Pentru preluarea datelor de la socket programul server fara conexiune
apeleaza functia recvform. Functia recvform nu
asteapta realizarea unei conexiuni. In schimb, raspunde oricaror solicitari care
sosesc la portul la care s-a inregistrat cu functia bind. Cand
functia recvform receptioneaza o datagrama de la socket, ea
memoreaza adresa de retea a procesului care a trimis datagrama, precum si
datagrama insasi.
De notat ca in cazul protocoalelor fara conexiune si clientul se
inregistreaza (leaga) la un port cu functia bind.
In esenta apelurile sunt aceleasi. Deosebirea intre client si server apare si
aici din faptul ca dialogul este initiat tot de client prin cererea de serviciu
pentru care foloseste functia sendto.
Aceste functii sunt: send, write, writev,
sendto, sendmsg.
Primele trei sunt destinate transmiterii datelor prin socketuri conectate, iar celelalte doua prin socketuri neconectate.
Nota. Pentru datele transmise prin socketuri neconectate se mai foloseste termenul de mesaj. Despre doua aplicatii ce comunica printr-un protocol fara conexiune se spune ca-si transmit mesaje.
Tabelul urmator descrie succind aceste cinci functii.
send |
Trimite date printr-un socket conectat. Poate utiliza flaguri pentru a controla comportamentul socketului. |
write |
Transmite date printr-un socket conectat folosind un buffer simplu. |
writev |
Transmite date printr-un socket conectat, folosind zone de memorie neadiacente ca buffer de date. |
sendto |
Transmite date printr-un socket neconectat, folosind un buffer simplu de mesaje. |
sendmsg |
Transmite date printr-un socket neconectat, folosind o structura de date flexibila ca buffer de mesaje. |
Aceste functii sunt: recv, read, readv,
recvfrom, recvmsg.
Primele trei sunt destinatereceptiei datelor prin socketuri conectate, iar celelalte doua prin socketuri neconectate.
Tabelul urmator descrie succind aceste cinci functii.
recv |
Receptioneaza date printr-un socket conectat. Poate utiliza flaguri pentru a controla comportamentul socketului. |
read |
Receptioneaza date printr-un socket conectat folosind un buffer simplu. |
readv |
Receptioneaza date printr-un socket conectat, folosind zone de memorie neadiacente ca buffer de date. |
recvfrom |
Receptioneaza date printr-un socket neconectat, folosind un buffer simplu de mesaje. |
recvmsg |
Receptioneaza date printr-un socket neconectat, folosind o structura de date flexibila ca buffer de mesaje. |
Cu cateva exceptii (functiile read, write si close ), detalii asupra acestor functii se gasesc in sectiunea Interfata Socket Berkeley implementata de Microsoft pe sistemele Windows.
![]()
© Cornel Mironel Niculae, 2004-2005
22-Nov-2005