Apeluri sistem pentru mecanismul de socket
In continuare vom prezenta o sinteza a celor mai dese apeluri folosite in comunicatia prin interfata socket. Sintaxa fiecarui apel este o legatura la paginile de manual corespunzatoare apelului respectiv.
Pentru a genera o aplicatie cu socket este necear apelul unor directive sistem specifice intr-o succesiune bine determinata de functia socket ce se doreste realizata.
Identificarea capetelor de comunicatie se face prin structura "struct sockaddr 646j96g " definita de regula in <sys/socket.h>:
struct sockaddr
In cazul comunicatiei prin Internet, toate adresele sunt compuse dintr-un numar de port, si adresa IP a calculatorului respectiv (cel pe care ruleaza procesul apelant - bind, sau calculatorul de la distanta pe care ruleaza procesul cu care se realizeaza comunicatia - connect si accept). Pentru specificarea acestor adrese se utilizeaza structura:
include <netinet/net.h>
struct sockaddr_in
Fiind vorba de o adresa de tip internet, primul camp trebuie sa aiba valoarea constantei predefinite AF_INET. Al doilea camp indica numarul portului, iar cel de-al treilea camp indica adresa IP a masinii dorite. Desi acest ultim camp are forma unei structuri, aceasta "ascunde" de fapt o variabila de tip long continand in format binar adresa IP respectiva.
int socket (int domeniu, int tip, int protocol)
unde:
- domeniu reprezinta familia protocoalelor utilizate in transferul informatiei. Valori uzuale: PF_INET (daca se vor utiliza protocoalele TCP/IP), PF_UNIX (pentru comunicatia prin intermediul unor fisiere UNIX de un tip special), PF_NS (protocoale Xerox Network Systems) etc. Pentru comunicatia in Internet se va folosi PF_INET.
- tip indica tipul comunicatiei (serviciul cerut mediului de comunicatie): SOCK_STREAM indica stabilirea unei comunicatii bazata pe construirea unei conexiuni intre sursa si destinatie. SOCK_DGRAM indica transferul unor mesaje scurte (datagrame) catre o anume destinatie. Comunicatia nu e bazata pe conexiune, este nesigura (uzual se implementeaza un protocol separat pentru a comunica prin intermediul datagramelor. SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET reprezinta alte modalitati de comunicatie. Uzual vom folosi doar primele doua modalitati de transfer.
protocol reprezinta un anume protocol din familia de protocoale specificate ca prim argument. In cazul utilizarii domeniului PF_INET, singurul protocol cunoscut este protocolul identificat prin valoarea 0.
Valoarea intoarsa de apelul socket() indica descriptorul ce a fost alocat pentru realizarea comunicatiei.
Asocierea unei adrese complete locale (adresa IP locala si numar de port local) se realizeaza prin apelul bind():
int bind (int sockd, struct sockaddr *adresa, int lung_adresa);
Functionalitate: asociaza descriptorului de tip socket "sockfd" adresa locala specificata complet in campurile structurii "adresa" al carei pointer este furnizat ca al doilea parametru. Lungimea acestei adrese este indicata prin valoarea ultimului parametru "lung_adresa".
Valoarea intoarsa de aceasta functie indica succesul apelului (0) sau o eroare (-1) al carei cod este indicat prin valoarea variabilei globale errno.
Specificarea adresei celuilalt capat de comunicatie (adresa completa IP si numarul portului destinatie) este realizata diferit in functie de tipul de comunicatie specificat in momentul creerii descriptorului socket.
int connect (int sockfd, struct sockaddr *adresa, int lg_adresa);
Functionalitate: asociaza descriptorului de tip socket "sockfd" adresa destinatie specificata complet in campurile parametrului "adresa". Dimensiunea in octeti a structurii "adresa" este indicata prin valoarea parametrului "lg_adresa". Valoarea intorsa de apel este un cod de eroare: 0=OK -1=eroarea errno.
int listen(s, int lung_coada);
Acest apel asociaza socket-ului "s" dimensiunea "lung_coada" a cozii de asteptare pentru cererile ce nu pot fi tratate la un moment dat. Valoarea intoarsa reprezinta succesul (0) sau esecul (-1) operatiei.Odata lungimea cozii specificate, server-ul se poate pune in asteptarea unei cereri prin intermediul apelului accept():
int accept(int s, struct sockaddr *adresa, int *addrlen);
Functionalitate: provoaca blocarea executiei server-ului pana in momentul receptionarii unei cereri (unui mesaj) transmis de catre un proces client. In acest moment, un socket separat este creat local, el urmand sa serveasca comunicatiei server -> client. Informatia relativa la adresa clientului este returnata de acest apel in structura "adresa" a carei lungime este intoarsa la randul ei in parametrul "addrlen".
struct hostent* gethostbyname(char *name);
Apelul primeste ca argument acest nume simbolic sub forma unui sir de caractere si intoarce un pointer la o structura ce indica o serie de caracteristici ale masinii UNIX respective. Aceasta structura e definita astfel:
#include <netdb.h>
struct hostent
Numele masinii respective, ca si totalitatea celorlaltor nume sub care ea este cunoscuta (alias-uri) sunt continute in primele doua campuri ale acestei structuri. Campul h_addrtype contine in cazul masinilor ce au atribuite adrese IP valoarea constantei AF_INET. Campul h_length indica lungimea binara a tipului de adresa utilizat (in cazul adreselor IP aceasta lungime este de 4 octeti).
Ultimul camp reprezinta un vector de adrese sub care aceasta masina e recunoscuta in retea. Fiecare astfel de adresa este de fapt un sir de h_length octeti.
Functionalitate: Odata ce un socket nu mai este de interes, el poate fi eliminat aplicand close asupra descriptorului sau. Daca datele sunt asociate cu un socket ce asigura o livrare sigura (de exemplu un socket stream), dupa o operatie de close sistemul va continua sa transfere datele. Totusi, dupa o perioada destul de lunga de timp, daca datele nu sunt livrate, ele vor fi sterse.
Daca un utilizator nu doreste sa mai utilizeze datele respective, el trebuie sa realizeze un shutdown asupra unui socket inainte de a-l inchide:
unde mod are valoarea 0 daca utilizatorul nu mai este interesat sa citeasca datele, 1 daca nu se mai face transmitere de date, 2 daca nu se mai face nici transmisie, nici receptie de date.
Comunicatia prin socketi:
sendto(sockfd, buf, lg_buf, flags, (struct sockaddr *)&spre, lg_spre);
recvfrom(sockfd, buf, lg_buf, flags, (struct sockaddr *)&dinspre, &lg_dinspre);
Functionalitate: pentru transmisia/receptia de date prin socketi de tip datagram.
Exemplu de transmitere-receptie date pe un socket conectat:
int bytes_sent;
int bytes_received;
char data_sent[256];
char data_received[256];
int send(int socket, char *buf, int buflen, int flags);
int recv(int socket, char *buf, int buflen, int flags);
int s;
bytes_sent=send(s,data_sent,sizeof(data_sent),0);
bytes_received=recv(s,data_received,sizeof(data_received),0);
Exemplu de transmitere-receptie date pe un socket neconectat:
int bytes_sent;
int bytes_received;
char data_sent[256];
char data_received[256];
struct sockaddr *adresa;
int sendto(int socket, char *buf, int buflen, int flags,
struct sockadrr *adr, int adrlg);
int recv_from(int socket, char *buf, int buflen, int flags
struct sockaddr *adr, int *adrlg);
int s;
bytes_sent=send(s,data_sent,sizeof(data_sent),0 , adresa, sizeof(*adresa));
bytes_received=recv(s,data_received,sizeof(data_received),0, adresa, sizeof(*adresa));
|