Dupa cum ati "observat" , din lectiile precedente , multe se pot face in C . Un lucru foarte important pentru un viitor programator "inrait" este
Utilizarea socketurilor .
Pentru a putea "coda in voie" , trebuie intai sa intelegem notiunea de
SOCKET .Voi recurge la un exemplu , din viata de zi cu zi , pentru aceasta.
Pentru a comunica cu colegul de banca la telefon ( din diverse motive ) , trebuie satisfacuti urmatori pasi : ( P.S. sa ai telefon ; iei telefonul , tastezi numarul -> suni si astepti ca respectivul sa raspunda ). Atat timp cat cei doi comunica , doua parti
opuse sunt implicate in proces , conectate una cu cealalta prin
reteaua telefonica .
Care e asemanarea intre un
SOCKET pe
Linux si un telefon ? Socketii pot fi comparati cu telefoanele , fiind puncte "finale" de comunicatie.Pentru ca tu , sa suni pe cineva , trebuie sa stii numarul de telefon al respectivului si respectiv sa-l apelezi.Socketul este ca un telefonul ( are atasat o adresa ) , pentru ca alt socket , sa-l poate apela prin intermediul adresei respective , (prin reteaua de comunicatie).
Acum putem trece serios pe codat .
Stiti ca Linux este o "aglomerare de fisiere" si socketurile se aseamana mult cu fisierele . Precum si fisierele , la crearea ( cu succes ) a unui socket , acesta primeste descriptor ( socket descriptor ).
1. Crearea socketurilor Dupa cum spuneam mai devreme , socketurile returneaza un
socket descriptor ( un numar ) , daca au fost create cu succes.Acesta le
identifica ).
int socket ( int domain , int type , int protocol )
La fel ca si functia
open() ( care creaza un "descriptor de fisier" pentru a putea accesa/gasi fisierele / device-urile din sistem ) , asa si
]socket() creaza un socket descriptor pentru a accesa computerele din retea/Internet . Frumoasa analogie , nu ?
Va intrebati ce reprezinta notatiile de mai sus :
domain = domeniul socketului .Adica ?
* local : comunicare intre socketuri la nivel local ( pe PC-ul pe care se ruleaza programul )
* Internet : stackul TCP/IP , IPX , Rose , Apple, pentru comunicare intre socketuri pe retea / Internet ( va aduceti aminte de exemplul telefoanelor ).
*PF_INET
*PF_LOCAL
*PF_INET6
*PF_IPX
*PF_APPLETALK
type = tipul socketului , cam ciudat nu ? Hint : cum se face transferul de date .
*SOCK_STREAM
*SOCK_DGRAM
*SOCK_RAW
protocol = pentru inceput il consideram 0.
Un exemplu ar fi bun .
int sock;
sock = socket ( PF_INET,SOCK_STREAM,0);
Ce se intampla defapt ? Se deschide un socket ( de comunicare ) cu urmatoarele propietati. Socketul va face comunicarea pe Internet , intre terminale ( PC-uri remote ) .
*
PF_INET semnifica acest lucru ( comunicarea pe Internet ).
*
-SOCK_STREAM e metoda de transmisie de date , aici prin
TCP. Metoda reliabila de transfer date
vs*
- SOCK_DGRAM , metoda folosind
UDP , nereliabila ( daca datele se pierd , nu se mai ocupa cu retransmisia) .
*Integerul
sock , este
descriptul de socket.Acesta identifica socketul pentru a putea fi folosit la schimbul de date.
De retinut : Daca valoarea descriptorului ( care este un integer ) e negativa ( < 0 ) , socketul nu a fost creat .
Daca e pozitiva , socketul a fost creat cu succes. Aceasta e bine de stiut , daca lucram "intens" si avem nevoie sa ne ocupam de toate erorile.Desigur sunt niste functii / variabile predefinite , pentru lucrul cu
erorile .
Putem folosi pentru asta codul simplu de mai jos . Creem un socket de Internet , transmisie date reliabila (
TCP ).
int sock;
sock = socket (PF_INET , SOCK_STREAM , 0 );
if sock < 0
printf(" Error " );
Mai jos este un cod minimal de atribuire date ( adresa / port / tip ) unui socket . Acestea sunt valorile la care poate fi contactat. ( numarul de telefon ).
2. Adresa socket struct sockaddr_in adr_inet; /* structura tipul de date adresa , etc ..*/
adr_inet.sin_family=AF_INET;
adr_inet.sin_port=htons(130);
adr_inet.sin_addr.s_addr = htonl(INADDR_ANY);
Cum v-ati dat bine seama , aceste detalii arata tipul , portul si adresa ( aici INADDR_ANY , orice adresa ) la care poate fi contactat socketul .
*
AF_INET : semnifica ca acest socket , va fi folosit pentru schimb date cu alte socketuri la nivel
retelistic ,
Internet , nu la nivel local.
*
130 : portul local , la care serverul va accepta conexiuni .
-valoarea
0 , va alege un port aleatoriu , nu unul prestabilit. ( gen 130 . ca mai sus ).
INADDR_ANY : semnifica , ca socketul isi primeste conexiuni pe toate IP-urile ( computerului local ) .De preferat e sa punem un IP prestabilit , pentru o mai buna comunicare fara de eroare
3. BIND :
Aveti un exemplu mai jos :
int z;
(z = bind (sock,(struct sockaddr * )&adr_inet,sizeof(adr_inet)) < 0 )
printf(" ERROR ");
BIND() primeste ca valoare un integer ( int ) . Cum va dati seama daca e negativ ,
nu s-a "bindat" ( atasat adresa de socket ) cu succes.
- are ca parametri ,
sock-ul , (SOCKETUL) , pe care l-am declarat mai sus ; adresa acestuia ( ii bindam , alipim socketului adresa si detaliile respective ) , si lungimea adresei .
BIND() , cum ii zice si numele , lipeste ( adresa / port / tip ) de socket .
-rostul lui ? : uneori este cu adevarata nevoie ( pentru anumite servicii si nu numai ) ca un server sa aiba alipit un anumit port / adresa pentru a se face schimbul "corect" de informatii.
4. LISTEN() - acesta defineste cate conexiuni
simultane va accepta socketul creat.
listen(sock,5);
Deci dupa cum va dati seama , socketul creat de noi mai devreme , va accepta maxim 5 conexiuni
simultane - cei doi parametri : primul
socketul , al doilea numarul de conexiuni
simultane , maxim acceptate.
5. CONNECT() -conectarea la un socket remote ( stiind datele respectivului ) ,eventual pentru un schimb de informatii.
Clienti se conecteaza la servere

, serverele asculta LISTEN () si accepta conexiuni ACCEPT () . E bine de stiut , in ce parte a codului ( sursa sau client ) se vor prezenta functiile / call-urile de sistem pe care le prezint.
if( connect(sock,(struct sockaddr *) &server, sizeof(server)) < 0){
printf("Eroare la conectare");
-
connect primeste ca parametri , socketul ( prin care se face conexiunea ) , datele ( adresa / port / detalii ) unde se face conexiunea . Daca acesta e negativ , conexiunea nu s-a putut efectua ( din anumite motive . EX : serverul nu mai accepta conexiuni .)
6. ACCEPT Spuneam mai devreme ceva de ACCEPT () . Acesta apare in partea server a programului , si accepta conexiuni de la clientul.
-clientul incearca CONNECT() , (sa se conecteze) , serverul il asculta [ LISTEN() si accepta ACCEPT() ]. Simplu , nu ? Sa vedem sintaxa.
lc = sizeof(struct sockaddr_in);
if( (sc = accept(sock, (struct sockaddr *) &adr_inet ,&lc)) < 0)
{
printf("Eroare la acceptarea conexiunii");
}
-serverul accepta conexiuni , pe socketul
sock (creat mai sus) ,cu propietatile adr_inet ( adresa/ port / etc ) .
-daca e negativ , acesta nu a putut accepta conexiunea , (poate fi din motive tehnice , sau nu mai asculta , deoarece s-a incarcat deja numarul maxim de conexiuni simultane de la LISTEN().)
Deci practic , pana acum , ce am facut . Recapitulam :
*creare socket
*atribuire adresa/port socketului
*BIND() adresa/port socketului ( Optional )
*LISTEN () accepta conexiuni serverul
*CONNECT() : conectare client - server
*ACCEPT() : accepta conexiuni serverul de la client
Ce mai ramane de facut ? Schimbul practic de informatii

Vom exemplifica , prin trimiterea de la server a stringului "
Hello World" , catre client .
Sunt mai multe functii de
trimitere si
primire de mesaje :
SEND() vs
RECV() . Le voi prezenta eu minal mai jos.
7. SEND() gets(buffer);
send(sock,buffer,bufsize,0);
Dupa cum observati , nu am mai dat sintaxa , ci am trecut direct la exemplu .
- se citeste un sir de caractere ( declarat buffer ) , apoi se trimite socketului remote ( server/client ).
SEND() primeste ca parametri , socketul : prin care se trimite ( cuprinde valorile / datele adresa port , unde va ajunge informatia ) , mesajul de trimis ( stringul buffer ) si bufsize ( numarul de caractere ale stringului ).Se poate calcula usor cu functia
strlen(buffer) ).
8. RECV()Acesta primeste sirul de caractere trimis de client / server , si la comanda noastra , poate sa fie afisat mesajul pe ecran , sau scris intr-un fisier sau cine stie ce altceva se poate face ( depinde de voi ).
recv(sock,buffer,bufsize,0);
Are aceeasi sintaxa ca
SEND() , doar ca aici nu se mai citeste bufferul , ci este primit de la socketul "remote" , care l-a trimis mai sus.
Sper ca am reusit , desi nu cred ( ca se poate in numai o lectie ) , sa va dau o tenta a ce inseamna
Utilizarea socketurilor .Voi prezenta intr-o extensie aferenta acestei lectii , cateva exemple practice de
client - server , care folosesc functiile de mai sus.Poate veniti chiar voi cu exemple , dar si cu intrebari . ( P.S. : voi mai bibili aceasta lectie , deoarece cred ca la prima mana
sigur am scapari ).
Cheer's ! :read2: