Laborator 5

4

Transcript of Laborator 5

Page 1: Laborator 5

8 Modelul client/server - TCP

In cadrul aplicatiilor in retea modelul cel mai frecvent intalnit este client/server incare un server ofera anumite servicii anumitor clienti ruland pe aceeasi masina sau la distanta(pe alte calculatoare conectate la retea).

Serverul poate satisface cererile provenite de la clienti in mod iterativ (la un momentdat serverul va deservi cereri provenite de la un singur client, secvential pentru toti clientii lui)sau concurent (mai multe cereri provenite de la clienti multipli vor fi procesate simultan).

8.1 Server TCP iterativ

Modelul general al unui server iterativ respecta ordinea urmatoarelor apeluri de sistem:

• socket() creaza un socket care va trata conexiunile cu clientii;

• pregatirea structurilor de date (continute in sockaddr_in) pentru a atasa socket-ulla portul folosit de aplicatie;

• bind() ataseaza socket-ul la port;

• listen() pregateste socket-ul pentru ascultarea in vederea stabilirii conexiunii cuclientii;

• accept() accepta realizarea unei conexiuni cu un anumit client (acest apel blocheazaprogramul pana la aparitia unei cereri de conectare din partea unui client);

• procesarea cererilor clientului - schimb de mesaje intre server si client folosindu-sedescriptorul de socket returnat de accept(), prin apelul primitivelor read() siwrite();

• close() inchiderea conexiunii cu clientul la terminarea dialogului cu acesta;

• shutdown() inchiderea directionala a conexiunii cu clientul.

12

Page 2: Laborator 5

Conexiunea client-server, odata stabilita, ramane valida pana cand, fie clientul, fieserverul o intrerup in mod explicit sau nu. Socket-ul utilizat pentru aceasta conexiune senumeste socket orientat conexiune. Un socket poate fi la un moment dat pentru mai multeconexiuni.

8.1.1 Primitiva bind()

Pentru a putea fi folosit efectiv, un socket va trebui atasat la portul masinii la careserverul va astepta cereri de conexiune din partea posibililor clienti. Acest lucru se realizeazaprin intermediul primitivei bind().

#include <sys/types.h>

#include <sys/socket.h>

int bind(int sockd, struct sockaddr *addr, socklen_t addrlen);

13

Page 3: Laborator 5

Structura sockaddr este o structura folosita pentru stocarea informatiilor de adresapentru orice tip de socket-uri.

struct sockaddr{

unsigned short sa_family; /* familia de adrese

(AF_UNIX, AF_INET, ...) */

char sa_data[14]; /* 14 bytes - adresa folosita */

}

Pentru internet se va folosi o structura particulara (derivata din sockaddr) numitasockaddr_in:

struct sockaddr_in{

short int sin_family; /* familia de adrese (AF_INET) */

unsigned short int sin_port; /* portul (0-65355) */

struct in_addr sin_addr; /* adresa Internet */

unsigned char sin_zero[8]; /* bytes neutilizati (zero) */

}

Adresa Internet este stocata in structura in_addr care are definitia:

struct in_addr{

unsigned long int s_addr /* 4 bytes ai adresei IP */

}

Serverul va putea folosi constanta INADDR_ANY pentru a se utiliza adresa IP a masiniipe care ruleaza procesul (aceasta asigura independenta codului de adresa IP a calculatoruluipe care se va executa serverul).

La apelul primitivei bind() se poate folosi 0 in loc de un numar de port valid. Inacest caz se va alege in mod automat un port gasit liber si va fi asociat socket-ului in cauza.

Pentru oferirea de servicii nestandard se recomanda folosirea porturilor > 1024. Valorilede la 1 la 1023 sunt rezervate serviciilor sistem standard:

• 80 - HTTP (HyperText Transfer Protocol - WWW );

• 23 - telnet;

• 21 - FTP;

• 22 - SFTP (Secret File Transfer Protocol);

• 25 - SMTP (Simple Mail Transfer Protocol);

Pentru vizualizarea unei liste a perechilor port-serviciu standard furnizate de catresistem se poate accesa fisierul /etc/services.

14

Page 4: Laborator 5

8.2 Primitiva listen()

Dupa atasarea portului, serverul va trebui sa astepte viitoare conexiuni de la diversiclienti si sa le rezolve cererile. Pentru aceasta se utilizeaza apelul listen() urmat deaccept().

#include <sys/socket.h>

int listen(int sockd, int backlog);

Al doilea parametru va stabili numarul de conexiuni permise in coada de asteptare aconexiunii cu clientii. Uzual, valoarea sa este 5.

8.3 Primitiva accept()

Acceptarea propriu-zisa a conexiunilor se va realiza cu accept():

#include <sys/types.h>

#include <sys/socket.h>

int accept(int sockd, struct sockaddr *addr, socklen_t *addrlen);

Acest apel va returna un descriptor de socket corespunzator clientului a carui conexiunea fost acceptata. Noul descriptor poate fi folosit pentru a trimite si receptiona date prinsend(), write(), recv() sau read().

8.4 Primitivele send() si recv()

#include <sys/types.h>

#include <sys/socket.h>

int send(int sockd, char *buf, int len, int flags);

int recv(int sockd, char *buf, int len, int flags);

8.5 Primitivele close() si shutdown()

Inchiderea conexiunii se poate face prim apelul primitivelor close() sau shutdown().In cazul primitivei close() orice incercare de a citi sau scrie folosind un socket inchis vagenera eroare. Pentru a controla modul de inchidere al socket-ului se va folosi primitivashutdown().

#include <sys/socket.h>

int shutdown(int sockd, int how);

15

Page 5: Laborator 5

8.6 Client TCP

In cazul unui client TCP, apelul primitivei accept() va fi inlocuit cu primitivaconnect().

#include <sys/types.h>

#include <sys/socket.h>

int connect(int sockd, struct sockaddr *addr, socklen_t addrlen);

Structura addr va contine adresa IP si portul serverului la care se va conecta clientul.

8.7 Conversia datelor

Comunicarea dintre server si client se realizeaza in cadrul unei retele eterogene cuconfiguratii hardware pe care programatorul nu le poate prevedea. Pentru a se asiguraindependenta transferului de date, s-a convenit ca octetii pe retea sa respecte o anumitaordine de codificare. Ordinea octetilor dintr-un cuvant (word - 2 octeti) poate fi rumatoarea:

• big endian cel mai semnificativ octet este primul (codificare folosita de procesoareleMotorola);

• little endian cel mai semnificativ octet este al doilea (codificare folosita de procesoareleIntel).

Pentru ca programele sa fie independente de codificare se folosesc o serie de functii deconversie de la codificarea de retea la cea a calculatorului gazda (pentru folosirea lor trebuieinclus fisierul netinet/in.h).

• htons() conversia unui intreg scurt (2 octeti) de la gazda la retea (host to networkshort);

• htonl() conversia unui intreg lung (4 octeti) de la gazda la retea (host to networklong);

• ntohs() conversia unui intreg scurt (2 octeti) de la retea la gazda (network to hostshort);

• ntohl() conversia unui intreg lung (4 octeti) de la retea la gazda (network to hostlong);

Membrii sin_port si sin_addr ai structurii sockaddr_in trebuie sa fie stocatiin codificarea de retea. Pentru a asigura conversia adreselor IP de la formatul intern (patrubytes) la cel uzual (patru octeti despartiti de punct) sau invers se vor folosi functiile:

16

Page 6: Laborator 5

• inet_addr converteste un sir de caractere continand o adresa IP la intreg. In caz deeroare returneaza INADDR_NONE;

• inte_aton converteste un sir de caractere continand o adresa IP la intreg. In caz deeroare returneaza 0;

• inte_ntoa converteste o adresa IP de la intreg la sir de caractere.

Bibliografie

[1] Sabin Buraga, Gabriel Ciobanu, Atelier de programare in retele de calculatoare, Polirom,Iasi, 2001

17