programarea în reţea (partea i)
TRANSCRIPT
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Retele de calculatoareProgramarea in retea I
SabinCorneliu Buraga
http://www.infoiasi.ro/~busaco
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
“If at first you don’t succeed,you must be a programmer.”/usr/games/fortune
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Cuprins
• Modelul client/server• API pentru programarea in retea• Socket‐uri BSD• Modelul client/server TCP
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Modelul client/server
Paradigme ale comunicarii in retea:
modelul client/server
apelul procedurilor la distanta (RPC)
comunicarea punct‐la‐punct (peertopeer – P2P)
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Modelul client/server
• Proces server– Ofera servicii obtinute prin retea– Accepta (iterativ sau concurent) cereri de la un proces client, realizeaza un anumit serviciusi returneaza rezultatul
• Proces client– Initializeaza comunicarea cu serverul– Solicita un serviciu, apoi asteapta raspunsul serverului
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Modelul client/serverClient
ProcessClient
ProcessProcessServer
TerminalServer
PrinterServer
FileServer
MemoryServer
Servicii nucleu (kernel)
ClientProcess
ClientProcess
ProcessServer
TerminalServer
PrinterServer
FileServer
MemoryServer
Kernel Kernel Kernel Kernel Kernel Kernel Kernel
O singura masina
Masini multiple (conectate la retea)
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Modelul client/server• Moduri de interactiune (via canale de comunicatie):
orientat‐conexiune – se foloseste TCPneorientat‐conexiune – se utilizeaza UDP
• Implementare:iterativa – fiecare cerere e tratata pe rind, secventialconcurenta – cererile sint procesate concurent
Procese copil pentru fiecare cerere de procesatMultiplexarea conexiuniiTehnici combinate
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
API retea• Necesitatea existentei unui API pentru realizarea de aplicatii in retea– Interfata generica pentru programare– Suport pentru comunicatii orientate‐conexiune siprin mesaje
– Compatibilitate cu serviciile I/O comune– Independenta de hardware si de sistem de operare– Suport pentru familii (suite) de protocoale multiple– Independenta in reprezentarea adreselor– Oferirea de servicii speciale pentru aplicatii
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
API retea• TCP/IP nu include definirea unui API• Se pot utiliza mai multe API‐uri pentru programarea aplicatiilor Internet (TCP/IP)– Socket‐uri BSD (Berkeley System Distribution)– TLI (Transport Layer Interface) – AT&T, XTI– Winsock– MacTCP
• Functii oferite: specificare de puncte terminale locale si la distanta, initiere si acceptare de conexiuni, trimitere si receptare de date, terminare conexiune, tratare erori
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Cuprins
• Interfata de programarea aplicatiilor (API) bazata pe socket‐uri BSD– Caracterizare– Creare– Primitive
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket• Socket‐uri BSD (Berkeley System Distribution)• Facilitate generala, independenta de hardware, protocol si tipul de transmitere, pentru comunicarea intre proceseaflate pe masini diferite, in retea
• Suporta pentru familii multiple de protocoale– Protocolul domeniului UNIX pentru comunicatii(locale) intre masini UNIX (e.g., uucp)
– Protocolul domeniului Internet folosind TCP/IP– Altele: XNS Xerox, ISO/OSI,…
• Independenta in reprezentarea adreselor
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket• Abstractiune a unui punct terminal (endpoint) la nivelul transport
• Utilizeaza interfata de programareI/O existenta(similar fisierelor, pipe‐urilor, FIFO‐urilor etc.)
• Poate fi asociat cu unul/mai multe procese, existind in cadrul unui domeniu de comunicatie
• Ofera un API pentru programarea in retea, avind implementari multiple
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket
Similar unui descriptor de fisier
Diferente apar la creare si la diferite operatiunide control al socket‐urilor
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket | primitive de baza
socket() creeaza un nou punct terminal al conexiuniibind() ataseaza o adresa locala la un socketlisten() permite unui socket sa accepte conexiuniaccept() blocheaza apelantul pina la sosireaunei cereri de conectare (utilizata de serverul TCP)
connect() tentativa (activa) de stabilire a conexiunii(folosita de clientul TCP)
send()/receive() trimitere/receptare de date via socketclose() elibereaza conexiunea (inchide un socket)shutdown() inchide directional un socket
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket
• Alte apeluri– citire de dateread() / readv() / recvfrom() / recvmsg()
– trimitere de datewrite() / writev() / sendto() / sendmsg()
– multiplexare I/Oselect()
– administrarea conexiuniifnctl() / ioctl() / setsockopt() / getsockopt()getsockname() / getpeername()
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri|tabela de descriptori
Tabela de descriptori
0
1
2
3
4
Family: AF_INETService: SOCK_STREAMLocal IP: 193.231.30.197Local Port: 80Remote IP: 19.132.6.78Remote Port: 3726
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri|creare• Apelul de sistem (primitiva) socket()#include <sys/types.h>#include <sys/socket.h>
int socket (int domain, int type, int protocol)
Domeniul de comunicare: AF_UNIX, AF_INET,
AF_ROUTE
Protocolul utilizatpentru transmitere
(uzual: 0 pentru niv. transp.)
Modalitatea de realizare a comunicarii: SOCK_STREAM, SOCK_DGRAM, SOCK_RAW
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri|creare• Valoarea de retur– Succes: descriptorul de socket creat– Eroare: –1
• Raportarea erorii se realizeaza via errno– EMFILE – ENFILE– EACCES– EPROTONOSUPPORT– ENOMEM– ENOBUFFERS– EINVAL
Constantedefinite in errno.h
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri
• Domeniul & tipul unui socket si protocoalele folosite
AF_LOCAL ≡ AF_UNIX(din motive istorice)
AF_INET AF_INET6 AF_LOCAL AF_ROUTE SOCK_STREAM TCP TCP Da SOCK_DGRAM UDP UDP Da
SOCK_RAW IP IPv6 Da
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri• Observatii
– Primitiva socket() aloca resursele necesareunui punct terminal de comunicare, dar nu stabileste modul de adresare
– Socket‐urile ofera un mod generic de adresare– Pentru TCP/IP trebuie specificate (adresa IP, port)– Alte suite de protocoale pot folosialte scheme de adresare
• Tipuri POSIX: int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, u_char, u_short, u_int, u_long
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri• Tipuri POSIX folosite de socket‐uri:
– sa_family_t – familia de adrese – socklen_t – lungimea structurii de memorare – in_addr_t – adresa IP (v4) – in_port_t – numarul de port
• Specificarea adreselor genericestruct sockaddr {
uint8_t sa_len;sa_family_t sa_family; char sa_data[14];
};
Tipul de adresa
Valoarea adresei
Utiliz. de
nucleu
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri
• Tipul sockaddr permite oricare tip de adresare• Exemplu: folosirea socket‐urilorpentru comunicarea dintre studenti– Tipul de adresa: AF_STUDENTS– Valori de adrese: Zaq⇔ 1, Moko⇔ 2, Tux ⇔ 3,…
– Initializarea structurii AF_STUDENTSpentru a indica un anumit student: struct sockaddr un_stud;un_stud.sa_family = AF_STUDENTS;un_stud.sa_data[0] = 3;
Tux
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri• Pentru AF_INET vom avea nevoie de 16 biti – numarul de port si de 32 biti – adresa IPv4
• Se foloseste o structura speciala: sockaddr_instruct sockaddr_in {
uint8_t sin_len;sa_family_t sin_family;in_port_t sin_port;struct in_addr sin_addr; char sin_zero[8];
};struct in_addr {
in_addr_t s_addr;};
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri
sin_lensa_lensa_family
sa_data
AF_INETsin_port
sin_addr
sin_zero
sockaddr sockaddr_in
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri• Toate valorile stocate in sockaddr_in vor respectaordinea de codificare a retelei (network byte order)sin_port un numar de port TCP/IPsin_addr o adresa IP
• ‘h’ : host byte order ‘n’ : network byte order• ‘s’ : short (16 biti) ‘l’ : long (32 biti)
uint16_t htons(uint16_t);uint16_t ntohs(uint_16_t);
uint32_t htonl(uint32_t);uint32_t ntohl(uint32_t);
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri• Pentru IPv6, se foloseste sockaddr_in6struct sockaddr_in {u_int16_t sin6_family; /* AF_INET6 */u_int16_t sin6_port;u_int32_t sin6_flowinfo;u_int32_t sin6_scope_id;struct in6_addr sin6_addr; };
struct in6_addr {unsigned char s6_addr[16];
};
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri|asignarea unei adrese• Asignarea unei adrese la un socket existent se realizeaza cu bind()
int bind ( int sockfd, const struct sockaddr *myaddr,int addrlen );
• Se returneaza: 0 succes, –1 eroare variabila errno contine eroarea efectiva: EBADF, ENOTSOCK, EADDRINUSE, EINVAL, EACCESS
const!
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri|asignarea unei adrese• Exemplu:
#define PORT 7000int sd, eroare;struct sockaddr_in adresa;
sd = socket (AF_INET, SOCK_STREAM, 0); /* TCP */adresa.sin_family = AF_INET; /* umplerea structurii */adresa.sin_port = htons (PORT); /* portul */adresa.sin_addr = htonl (adresaIP); /* adresa IP */
eroare = bind (sd, (sockaddr *) &adresa, sizeof (adresa));
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri|asignarea unei adrese• Utilizari ale lui bind()
– Serverul doreste sa ataseze un socket la un port pre‐stabilit (pentru a oferi servicii via acel port)
– Clientul vrea sa ataseze un socket la un port specificat– Clientul cere sistemului de operare sa asignezeorice port disponibil
• In mod normal, clientul nu necesita atasareala un port specificat
• Alegerea oricarui port liber: adresa.port = htons (0);
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri|asignarea unei adrese
• Alegerea adresei IP la bind()– Daca gazda are asignate mai multe adrese IP?– Cum se rezolva independenta de platforma?
• Pentru a atasa un socket la adresa IP locala, se va utilizain locul unei adrese IP constanta INADDR_ANY
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri|asignarea unei adrese
• Conversia adreselor IP:int inet_aton ( void *, struct in_addr *);ASCII “x.x.x.x” ⇒ reprezentare interna pe 32 biti
char *inet_ntoa ( struct in_addr );reprezentare 32 biti (network byte order) ⇒ ASCII “x.x.x.x”
vezi si functia inet_addr()
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri|asignarea unei adrese
• Observatii:– Pentru IPv6 in locul constantei INADDR_ANYse va folosi – vezi antetul netinet/in.h:serv.sin6.addr = in6addr_any;
– Functiile de conversie pentru IPv6 sunt:inet_pton()inet_ntop()
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri|listen()• Stabilirea modului pasiv de interactiune
– Adresa intotdeauna este cunoscuta– Nucleul sistemului va trebui sa accepte cereride conectare directionate la adresa la care este atasat socket‐ul3way handshake
– Conexiunile multiple receptionatevor fi plasate intr‐o coada de asteptare
– Se returneaza 0 = succes, –1 = eroare
int listen ( int sockfd, int backlog );
Socket TCP atasat unei adrese
Numarul de conex. din coada de astept.
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri|listen()
• Remarci:– Alegerea valorii backlog depindede aplicatie – in mod uzual 5
– Serverele HTTP ar trebui sa specificeo valoare backlog cit mai mare (din cauza incarcarii cu cereri multiple)
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri|accept()• Asteptarea conexiunilor din partea clientilor
– Cind aplicatia este pregatita pentru a trata o noua conexiune, va trebui sa interogam sistemul asupra unei alte conexiuni cu un client
– Se returneaza descriptorul de socket corespunzator punctului terminal al clientului sau –1 = eroare
int accept( int sockfd,struct sockaddr* cliaddr, socklen_t *addrlen );
Socket TCP (mod pasiv)
• trebuie initial sa fie egal cu lungimea structurii cliaddr• se va returna numarul de bytes folositi in cliaddr
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri|connect()• Incercarea de a stabili o conexiune cu serverul
– Stabilirea unui punct terminal (al serverului)– Nu necesita atasarea cu bind(), sistemulde operare va asigna o adresa locala (IP, port)
– Se incearca stabilirea unei conexiuni3way handshake
int connect( int sockfd,const struct sockaddr *server,socklen_t addrlen );
Socket TCP
Contine adresa serverului (IP, port)
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Socket‐uri|connect()• Returneaza:
– Valoarea 0 = succes– Valoarea –1 = eroare
• EISCONN• ETIMEDOUT• ECONNREFUSED• ENETUNREACH• EADDRINUSE• EINPROGRESS• EADDRNOTAVAIL• EAFNOSUPPORT
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
I/O TCP|read()• Apelul este blocant in mod normal, read() returneaza doar cind exista date disponibile
• Citirea de la un socket TCP poate returnamai putini octeti decit numarul maxim dorit
• Trebuie sa fim pregatiti sa citim cite 1 byte la un moment dat!
• Daca partenerul a inchis conexiunea si nu mai sunt date de primit, se returneaza 0 (EOF)
• Erori: EINTR – un semnal a intrerupt citirea, EIO – eroare I/O, EWOULDBLOCK – socket‐ul nu are date intr‐o citire neblocantaint read ( int sockfd, void *buf, int max );
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
I/O TCP|write()• Apelul este blocant in mod normal• Pentru un socket neblocant, write() poate scrie mai putin de num octeti
• Erori: – EPIPE – scriere la un socket neconectat– EWOULDBLOCK – nu se pot accepta date fara blocare, insa operatiunea este setata ca fiind neblocanta
int write ( int sockfd, void *buf, int num );
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
I/O TCP|exemplu#define MAXBUF 127 /* lungime buffer citire */char *cerere = “da-mi ceva”;char buf[MAXBUF]; /* buffer pentru raspuns */char *pbuf = buf; /* pointer la buffer */int n, lung = MAXBUF;
/* nr. bytes cititi, nr. bytes liberi in buffer */
/* trimitem cererea */write (sd, cerere, strlen (cerere));
/* asteaptam raspunsul */while ((n = read (sd, pbuf, lung)) > 0) {pbuf += n;lung -= n;
} Comunicarea dintre client si server
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Inchiderea conexiunii|close()
• Terminarea “gratioasa” a conexiunii• Dealocarea memoriei alocate socket‐ului
– 3way handshake pentru inchiderea conexiunii– Pentru procese care partajeaza acelasi socket, se decrementeaza numarul de referinte la acel socket; cind ajunge la 0, socket‐ul este dealocat
• Probleme– Serverul nu poate termina conexiunea, nu stie daca si cind clientul nu va mai trimite si alte cereri
– Clientul nu poate sti daca datele au ajuns la server
int close ( int sockfd );
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Inchiderea conexiunii|shutdown()• Inchiderea unidirectionala
– Cind un client termina de trimis cererile, poate apela shutdown() pentru a specifica faptul ca nu va mai trimite date pe socket, fara a dealoca socket‐ul
– Serverul va primi EOF si, dupa expedierea catre client a ultimului raspuns, va putea inchide conexiunea
int shutdown ( int sockfd, int dir );
• 0 nu se accepta operatii de citire (SHUT_RD)• 1 nu se accepta operatii de scriere (SHUT_WR)• 2 nu se accepta operatii I/O
inchidere in ambele sensuri (SHUT_RDWR)
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Metaphor for Good RelationshipsCopyright Dr. Laura’s Network Programming Corp.
To succeed in relationships…– you need to establish your own identity.– you need to be open & accepting.– you need to establish contacts.– you need to take things as they come, not as you expect them.
– you need to handle problems as they arise.
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Client/server TCP|server• Modelul unui server TCP iterativ
– Creare socket pentru tratarea conexiunilor cu clientii: socket()– Pregatirea structurilor de date (sockaddr_in) – Atasarea socket‐ului la adresa locala (port): bind()– Pregatirea socket‐ului pentru ascultarea portuluiin vederea stabilirii conexiunii cu clientii: listen()
– Asteptarea realizarii unei conexiuni cu un anumit client (deschidere pasiva): accept()
– Procesarea cererilor clientului, folosindu‐se socket‐ul returnatde accept(): succesiune de read()/write()
– Inchiderea (directionata) a conexiunii cu clientul: close(), shutdown()
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Client/server TCP|client
• Modelul unui client TCP iterativ– Creare socket pentru conectarea la server: socket()– Pregatirea structurilor de date (sockaddr_in) – Atasarea socket‐ului: bind() – optional– Conectarea la server (deschidere activa): connect()– Solicitarea de servicii si receptionarea rezultatelor trimise de server: succesiune de write()/read()
– Inchiderea (directionata) a conexiunii cu serverul: close(), shutdown()
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Rezumat
• Modelul client/server• API pentru programarea in retea• Socket‐uri BSD
– Caracterizare– Creare– Primitive
• Modelul client/server TCP
Dr. Sabin-Corneliu Buraga – www.infoiasi.ro/~busaco/
Intrebari?