Programmation Répartie - Sockets en C Partie 2 : socket TCP
Transcription
Programmation Répartie - Sockets en C Partie 2 : socket TCP
Programmation Répartie - Sockets en C Partie 2 : socket TCP Frédéric Guinand [email protected] IUT informatique / Université du Havre Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP TCP : Transmission Control Protocol mode connecté comme le téléphone connexion durable adresse indiquée une seule fois à l’établissement de la connexion exemples : ftp, telnet Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP UDP ↔ TCP UDP analogie courrier postal UDP : le serveur attend des messages en provenance de plusieurs clients UDP : à chaque reception, le serveur est disponible pour une autre connexion TCP analogie téléphone TCP : le serveur établit une connexion qui reste active avec UN client, durant la connexion le serveur est occupé TCP : lorsque la connexion entre le client et le serveur prend fin, le serveur devient disponible de nouveau TCP : si le serveur est occupé, tout nouveau client doit attendre son tour pour établir une connexion avec le serveur Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP Principe d’une application Client/Serveur TCP Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP Préparation des sockets pour la connexion Le client configuration de la socket server : remplissage des champs de struct sockaddr_in (avec le numéro IP et le numéro de port) création de la socket client : socket() Le serveur configuration de la socket création de la socket Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP Communication entre client et serveur Rappel UDP client et serveur attachent leur socket : bind() dès la fin de la création et de l’attachement de la socket côté client et de la socket côté serveur, la communication peut commencer sendto() et recvfrom() en TCP c’est différent Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP Communication entre client et serveur Le client demande une connexion avec le serveur connect() si le serveur est occupé, il est mis en attente Le serveur attachement de la socket : bind() le serveur se met à l’écoute des éventuels clients : listen() lorsqu’un nouveau client arrive, le serveur accepte la connexion : accept() ⇒ la communication peut maintenant commencer envoi d’information par write() reception d’informations par read() (ou recv() Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP bind() ↔ connect() bind() consiste à attacher la socket à une adresse locale connect() consiste à attacher la socket à un serveur distant Le serveur le serveur doit exécuter un bind(), pour permettre aux clients de se connecter à lui Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP Eléments communs les fichiers d’include la préparation de la socket, la création et l’attachement fichiers d’include #include <stdio.h> #include <string.h> #include <ctype.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> #include <netinet/in.h> #include <arpa/inet.h> Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP Configuration des informations de la socket déclaration d’une variable struct sockaddr_in renseignement des trois champs : sin_family = AF_INET sin_addr pour l’adresse IP sin_port pour le numéro de port Côté serveur struct sockaddr_in socket_locale ; socket_locale.sin_family = AF_INET ; /*adresse IP sans importance */ socket_locale.sin_addr.s_addr = htonl(INADDR_ANY) ; /* si le port est 5555 */ socket_locale.sin_port = htons(5555) ; Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP Côté client le client ne doit configurer qu’une structure sockaddr_in il doit renseigner les champs de cette structure sockaddr_in avec les informations de la machine sur laquelle le serveur est exécuté : numéro IP et numéro de port. struct sockaddr_in infos_serveur ; infos_serveur.sin_family = AF_INET ; // adresse IP du serveur (on suppose que l’adresse vaut 98...) // sinon il faut utiliser gethostbyname()... vous maîtrisez ça non ? infos_serveur.sin_addr.s_addr = inet_addr("98.23.68.34") ; // numéro de port du serveur (on le suppose égal à 5555) infos_serveur.sin_port = htons(5555) ; Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP Création des sockets Côté client int desc ; if((desc= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { printf("problème création socket \n") ; exit(1) ; } Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP Création des sockets Côté serveur int desc ; if((desc= socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { printf("problème création socket \n") ; exit(2) ; } Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP Attachement et préparation à la connexion Côté serveur if((bind(desc, (struct sockaddr *)&socket_locale, sizeof(socket_locale)) == -1) { printf("problème au moment de l’attachement \n") ; exit(1) ; } // après le bind, le serveur attend une connexion d’un client if(listen(desc,10) < 0) { printf("problème au niveau du listen \n") ; exit(3) ; } 10 est la longueur maximum de la file des connexions en attente Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP Connexion Côté client if((connect(desc, (struct sockaddr *)&infos_serveur, sizeof(infos_serveur)) == -1) { printf("problème au moment de la connexion \n") ; exit(4) ; } le client attend que la connexion soit acceptée pour engager les échanges Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP Connexion Côté serveur struct sockaddr_in infos_client ; int lg_infos_client ; int desc_sock_com ; if((desc_sock_com=accept(desc, (struct sockaddr *)&infos_client, &lg_infos_client) == -1) { printf("problème au moment de l’acceptation \n") ; exit(5) ; } → la primitive accept() retourne un nouveau descripteur de socket c’est désormais au travers de cette socket que client et serveur vont communiquer ! Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP La communication si l’exécution de socket, bind, connect, listen et accept s’est bien passée la communication peut commencer, deux primitives sont utilisées pour communiquer : int nbOctetsRecus = read(desc_socket,buffer,taille_buffer) int nbOctetsEnvoyes = write(desc_socket,buffer,taille_buffer) Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP En résumé Côté client int desc_socket ; struct sockaddr_in infos_serveur ; // création socket desc_socket = socket(AF_INET,SOCK_STREAM,0) ; // configuration informations serveur infos_serveur.XXX = YYY ; // connexion au serveur connect(desc_socket,&infos_serveur,sizeof(infos_serveur)) ; // lecture - écriture while(il y a des échanges) { write(desc_socket,buffer,sizeofbuffer) ; read(desc_socket,buffer,sizeobuffer) ; } Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP Côté serveur int desc_socket, desc_sock_com ; struct sockaddr_in infos_client, infos_serveur ; // création socket, configuration adresse serveur, attachement desc_socket = socket(AF_INET,SOCK_STREAM,0) ; infos_serveur.XXX = YYY ; bind(desc_socket,&infos_serveur,sizeof(infos_serveur)) ; // attente de connexions et gestion d’une connexion listen(desc_socket,taille-file-attente) ; desc_sock_com = accept(desc_socket, &infos_client,sizeof(infos_client)) ; // lecture - écriture while(il y a des échanges) { read(desc_sock_com,buffer,sizeofbuffer) ; write(desc_sock_com,buffer,sizeobuffer) ; } Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP Côté serveur pour servir plusieurs clients à la suite // création socket, configuration adresse serveur, attachement // attente de connexions listen(desc_socket,taille-file-attente) ; while(le serveur accepte des connexions) { desc_sock_com = accept(desc_socket, &infos_client,sizeof(infos_client)) ; // lecture - écriture while(il y a des échanges) { read(desc_sock_com,buffer,sizeofbuffer) ; write(desc_sock_com,buffer,sizeobuffer) ; } close(desc_sock_com) ; } Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP Côté serveur pour servir plusieurs clients simultanément // création socket, config adr serveur, attachement, attente listen(desc_socket,taille-file-attente) ; while(le serveur accepte des connexions) { desc_sock_com = accept(desc_socket, &infos_client,sizeof(infos_client)) ; pid = fork() ; if(pid == 0) { // je suis le fils close(desc_socket) ; while(il y a des échanges) { read(desc_sock_com,buffer,sizeofbuffer) ; write(desc_sock_com,buffer,sizeobuffer) ; } close(desc_sock_com) ; } else { close(desc_sock_com) ; } } Frédéric Guinand Programmation Répartie - Sockets en C Partie 2 : socket TCP