Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

Slides:



Advertisements
Présentations similaires
LES NOMBRES PREMIERS ET COMPOSÉS
Advertisements

Programmation réseau Les sockets de Berkeley
Synchronisation des processus père - fils
1 V-Ingénierie… La compétence au service de lexigence… vous présente.
Mode Message Asynchrone (interface Socket)
Protocole PPP* *Point-to-Point Protocol.
14 - Adresse IP et interfaces. Plan détude 1)Adresse IP dune interface 1)Résolution de nom vers IP statique 1)Service DNS 1)Spécification des interfaces.
- Couche 4 - Couche transport. Sommaire 1) Caractéristiques de la couche transport 2) Les protocoles TCP & UDP 3) Méthode de connexion TCP.
Présentation de l’application « Livret personnel de compétences »
Firewalling et NAT sous LINUX
Architecture de réseaux
C.
Les éléments de mémorisation
4.La connexion de données 4-1.Présentation 4-2.Le mode actif 4-3.Le mode passif 4-4.Les commandes.
Chap. 1 Structures séquentielles : listes linéaires
ESIEE Paris © Denis BUREAU I N Initiation à la programmation avec le langage Java.
FLSI602 Génie Informatique et Réseaux
User management pour les entreprises et les organisations Auteur / section: Gestion des accès.
Parallel Programming in C with MPI and OpenMP
1 Le protocole UDP Dominique SERET. Octobre 2000 Dominique SERET - Université René Descartes 2 UDP : User Datagram Protocol n UDP : protocole de transport.
Mr: Lamloum Med LES NOMBRES PREMIERS ET COMPOSÉS Mr: Lamloum Med.
Systèmes d'exploitations Les redirections d'entrées/sorties GRARI Mounir ESTO Année 2011.
Les requêtes La Requête est une méthode pour afficher les enregistrements qui répondent à des conditions spécifiques. La requête est donc un filtre.
Common Gateway Interface
ARCHITECTURE GLOBALE CAPTAGE Traitement DES des données GRANDEURS
Développement d’applications web
Points importants de la semaine Les fonctions. La portée. La passage par copie. Les tableaux.
Structures de données linéaires
Gestion des Périphériques
Synchronisation et communication entre processus
II. Chaînage, SDD séquentielles
Serveurs Partagés Oracle
Analyse des protocoles de la couche application
Labview Programmation réseau Communication par sockets
Les instructions PHP pour l'accès à une base de données MySql
Virtual Local Area Network
Configuration de Windows Server 2008 Active Directory
Les Réseaux Informatiques Le Modèle TCP/IP Clients & Serveurs Le protocole FTP Boukli HACENE Sofiane.
Les relations clients - serveurs
F Copyright © Oracle Corporation, Tous droits réservés. Créer des programmes avec Procedure Builder.
Les pointeurs Modes d’adressage de variables. Définition d’un pointeur. Opérateurs de base. Opérations élémentaires. Pointeurs et tableaux. Pointeurs et.
Programmation concurrente
ÉLÉMENTS DE BASE UNIX.
Signaux – Tubes La gestion des signaux La communication par tube
Christine Bonnet SOURCES : « Samples » dOracle, « Oracle 8 » R. Chapuis PRO*C – C ++
Réseaux Informatiques
Plan cours La notion de pointeur et d’adresse mémoire.
Vue d'ensemble Configuration d'adresses IP
Structures des données
Module : Technologies des serveurs réseaux : FTP Dynamic Host Configuration Protocol Présenter par : Mounir GRARI.
Gérer la sécurité des mots de passe et les ressources
LES PILES ET FILES.
Développement d’application client/serveur
PHP 5° PARTIE : LES COOKIES
Les Composants de l’architecture Oracle
Les listes de contrôle d’accès
CEG3585/CEG3555 Tutorat 2 Hi ver 2013.
 Requêtes MySQL en PHP Introduction
Advisor Advanced IP Présentation Télémaintenance Télésurveillance.
Programmation Système et Réseau
Les Réseaux Informatiques Clients & Serveurs Le protocole FTP Laurent JEANPIERRE DEUST AMMILoR.
Les sockets.
Les Réseaux Informatiques
Commutation de circuits
Couche transport du modèle OSI
 Formulaires HTML : traiter les entrées utilisateur
Architecture Client/Serveur
Client/Server Socket. Client/Serveur.
CentralWeb F. Playe1 Principes de base du routage IP Ce cours est la propriété de la société CentralWeb. Il peut être utilisé et diffusé librement.
1 UNIX AVANCE Yves PAGNOTTE – Janvier – LES PROCESSUS SOUS UNIX.
Transcription de la présentation:

Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000

Protocoles de l’Internet : rappels Interface du service de transport APPLICATION APPLICATION send Num. port UDP ou TCP receive PHY 1 PHY 2 ARP MAC 1 MAC 2 Data Link 1 Data Link 2 ICMP IP TCP UDP Endsystem sur réseau 1 Endsystem sur réseau 2 Routeur IP Numéro de port = identifie l’application à laquelle le paquet IP est destiné

Notion de socket (1) Permet d’établir un canal de communication bidirectionnel entre deux applications (plus exactement entre deux TSAPs) Socket UDP : paquets de taille variable, transport non fiable (pertes, duplications, erreurs possibles) Socket TCP : paquets de taille variable délivrés dans l’ordre et sans erreurs => Choisir le protocole en fonction des besoins de l’application : données informatiques (FTP, Telnet) : TCP, video : UDP

Notion de socket (2) Sous Unix les applications sont dénommées processus Les processus actifs sont répertoriées dans une table du système et identifiés par un pid (cf. commande ps) Lorsqu’il est actif, un processus possède un contexte d’exécution => variables d’environnement, table de descripteurs de fichiers ouverts …

Notion de socket (3) Mécanisme de communication entre applications sous Unix : - pipe (ou tube nommé) -> fichier - mémoire partagée (system V) - file de messages - sockets Lorsqu’un objet de ce type est créé par une application, le système lui alloue un identifiant. L’identifiant d’un socket est un descripteur analogue aux descripteurs de fichiers.

Fork et héritage Unix est un système multitâches : => un processus en cours d’exécution peut se dupliquer dynamiquement : fork() => après un fork(), deux applications : le processus père et le processus fils s’exécutent simultanément (en temps partagé ou bien en parallèle sur un système multiprocesseurs) => le processus fils hérite du contexte d’exécution du processus père

Terminaison de processus Le processus père attend habituellement la terminaison du processus fils : => wait(), attente passive : reçoit le signal SIGCLD (cf. table des signaux /usr/include/signal.h) Lorsque le processus père se termine sans avoir fait un wait (), le processus fils est rattaché au processus de PID 1 (init)

Recouvrement Le code du processus fils peut être dynamiquement remplacé par celui d’un exécutable stocké sur disque : => exec () Possibilité de passage de paramètres (ligne de commande) et des variables d’environnement Après un exec() le processus conserve toutes ses caractéristiques : PID, priorité, propriétaire et groupe réels, catalogue courant, terminal associé, masque de création de fichiers, descripteurs de fichiers ouverts, signaux ignorés (les autres signaux reprennent leur comportement par défaut)

Redirection des entrées/sorties Les descripteurs de fichiers 0,1 et 2 correspondent respectivement à : - l’entrée standard (clavier), - la sortie standard (écran), - la sortie erreur standard (écran) Ces fichiers spéciaux (mode caractère) sont ouverts par défaut lors de la création du processus La primitive système dup() permet de dupliquer un descripteur (ie. Toutes les lectures/écritures effectuées sur l’un des fichiers le sont aussi sur l’autre) => par ce mécanime, les fichiers standards peuvent être redirigés

Modèle de communication Un processus (le serveur) est en attente (à l’écoute) sur un numéro de port => tous les processus (les clients) connaissant l’adresse IP du serveur et le numéro de port peuvent lui envoyer des messages (requêtes) Le serveur traîte les messages entrants puis renvoie une réponse au client en utilisant le numéro de port source contenu dans l’en-tête du message En mode connecté (TCP) il y a établissement préalable d’une connexion

Programmation des sockets Les sockets sont identifiés dans le système par des descripteurs de même nature que les descripteurs de fichiers => les fichiers d’entrées/sortie standard (desc. 0,1 et 2) peuvent être redirigés sur des sockets => il y a héritage des descripteurs de sockets après un fork() Le descripteur d’un socket est renvoyé par la primitive socket(). Le processus peut alors effectuer des opérations de lecture/écriture car la communication est bidirectionnelle (!= tube) Les frontières de messages sont conservées

Domaine d’un socket(1) Domaine UNIX : AF_UNIX <sys/un.h> Les sockets sont locales au système et fournissent un mécanisme d’IPC (InterProcessus Communication) struct sockaddr_un { short sun_family; /* AF_UNIX */ char sun_path [108] /* référence UNIX */ };

Domaine d’un socket(2) Domaine internet : AF_INET struct in_addr { u_long s_addr; }; struct sockaddr_in { short sin_family; /* AF_INET */ u_short sin_port; /* numéro de port */ struct sin_addr; /* adresse internet */ char sin_zero[8]; /* champ de 8 zeros] */

Types de sockets SOCK_DGRAM : transport de données en mode non connecté. Dans le domaine AF_INET, le protocole UDP est utilisé. Les frontières de messages sont préservées. SOCK_STREAM : transport de données en mode connecté. Dans le domaine AF_INET, utilisation de TCP. Frontières de messages préservées et possibilité d’envoi de messages urgents. SOCK_RAW : permet l’accès au service de niveau 3 (émission/réception de paquets IP) SOCK_SEQPACKET : comme le type SOCK_STREAM mais ne permettant pas l’envoi de messages urgents

Création d’un socket int socket (domaine, type, protocole) int domaine; /* AF_INET, … */ int type; /* SOCK_DGRAM, … */ int protocole; /* 0 : protocole par défaut attribué par le système*/ Structure de données associée à un socket : type, domaine et protocole du socket état (en état de recevoir ou d’émettre) adresse des buffers de réception et d’émission pointeurs sur les données en émission/réception groupe de processus pour la gestion des signaux SIGURG, SIGIO

Binding : association socket/adresse int bind (sock, p_adresse, lg) int sock; /* descripteur de socket */ struct sockaddr *p_addresse; /* pointeur sur l’adresse */ int lg; /* longueur de l’adresse */ Après sa création un socket est accessible par son descripteur. Seuls des processus fils peuvent en hériter. Bind fournit un procédé de nommage d’un socket permettant à d’autres processus d’y accèder. Cas d’erreurs : descripteur incorrect (EBADF,ENOTSOCK), adresse incorrecte, inaccessible ou déjà utilisée (EADDRNOTAVAIL, EADDRINUSE, EACCESS), socket déjà associé à une adresse (EINVAL).

Binding dans le domaine AF_INET(1) Dans le domaine internet, le champ sockaddr est une structure sockaddr_in => choisir une adresse internet quelconque (INADDR_ANY) ou spécifier l’adresse d’une interface IP (gethostname() et gethostbyname()) => choisir le numéro de port (getservbyname() dans le cas d’un service existant) ou bien fixer un numéro non réservé (>= IPPORT_RESERVED) ou bien laisser le système choisir un numéro de port (initialiser le champ sin_port à zéro)

Binding dans le domaine AF_INET(2) Pour accéder à l’adresse associée à un socket en connaissant seulement son descripteur : int getsockname (sock, p_adr, p_lg) int sock; /* descripteur du socket */ struct sockaddr_in *p_addr; /* pointeur sur l’adresse */ int *p_lg; /* pointeur sur la longueur de l’adresse */ A l’appel p_lg = sizeof(struct sockaddr_in), au retour p_lg = longueur effective de l’adresse

Emission de datagrammes(1) int sendto(sock, ms, lg, option, p_dest, lgdest) int sock; /* descripteur du socket */ char *msg; /* adresse du message à envoyer */ int lg; /* longueur du message */ int option; /* =0 pour le type SOCK_DGRAM */ struct sockaddr *p_dest; /* pointeur sur adresse socket dest */ int lgdest; /* longueur adresse socket dest */ => retour = nombre de caractères envoyés ou –1 en cas d’échec (descripteur ou adresse du socket de destination invalide, taille de message ne permettant pas l’envoi d’un seul datagramme)

Emission de datagrammes(2) Pour envoyer une série de messages : int sendmsg (sock, msg, option) int sock; /* descripteur du socket en émission */ struct msghdr msg[]; /* tableau des en-têtes de messages */ int option; => cette primitive d’envoi peut être utilisée sans appel préalable à la primitive bind(). Le système associe le socket à une adresse lors de l’envoi du premier message.

Emission de datagrammes(3) Structure des en-têtes de messages à émettre <sys/socket.h> struct msghdr { caddr_t msg_name; /* adresse optionnelle */ int msg_namelen; /* taille de l’adresse */ struct iovec *msg_iov; /* tableau de messages */ int msg_iovlen; /* nombre d’élements du tableau */ caddr_t msg_accrights; /* inutilisé pour les sockets */ int msg_accrightslen; /* inutilisé pour les sockets */ }; Structure iovec <sys/uio.h> struct iovec { caddr_t iov_base; /* adresse du message */ int iov_len; /* longueur du message */ };

Réception de datagrammes (1) int recvfrom ( sock, msg, option, p_exp, p_lgexp) int sock; /* descripteur du socket */ char *msg; /* adresse mémoire du message reçu */ int lg; /* taille du buffer contenant le message */ int option; /* 0 ou MSG_PEEK*/ struct sockaddr *p_exp; /* adresse de l’expediteur */ int *p_lgexp; /* sizeof(p_exp) et longueur du résultat */ Le paramètre lg doit correspondre à la taille du message reçu, sinon des caractères sont perdus (il faut connaître la taille du message envoyé) Retourne le nombre de caractères reçus ou –1 en cas d’erreur

Réception de datagrammes (2) L’appel recvfrom est bloquant. Pour éviter l’attente de réception d’un message, utiliser fcntl ( sock, F_SETFL,FNDELAY|fcntl (sock, F_GETFL,0)); Pour répondre, le processus extrait l’adresse et le numéro de port de la structure sockaddr (sockaddr_in dans le domaine AF_INET); L’option MSG_PEEK permet de consulter le message sans l’extraire Pour recevoir une série de messages : int recvmsg ( sock, msg, option) int sock; /* descripteur du socket de réception */ struct msghdr [ ]; /* tableau des en-têtes reçus */ int option;

Communication client/serveur(1) Sur le serveur : - créér un socket de type SOCK_DGRAM (donner un numéro de port) - détacher le serveur du terminal de lancement (pas d’interruptions clavier possibles) - boucler en attente des messages : les lire par recvfrom( ), y répondre par sendto( ) Sur le client : - récupérer l’adresse du serveur (gethostbyname( )) - créer un socket, initialiser les champs (numéro de port, adresse @IPdest) - envoyer une requête par sendto ( ), lire la réponse par recvfrom ( )

Communication client/serveur(2) Les fonctions suivantes sont utilisées pour la programmation des sockets : - bzero : initialiser à zéro les champs d’une structure sockaddr - bcopy : initialiser le champ adresse (sin_addr) d’une structure sockaddr - htons : initialiser le champ port de la structure (little != big endian) Pour éviter l’attente active du serveur (while(1)), le service associé au numéro de port choisi pour le serveur peut être enregistré dans le fichier /etc/services. En modifiant le fichier /etc/inetd.conf, le processus daemon inetd prendra en charge la création d’un processus serveur sur réception d’un message de requête contenant le numéro de port du service (attente active, select, fork()). Inetd relit le fichier inetd.conf sur réception d’un signal SIGHUP.

Communication en mode connecté(1) L’information est échangée après établissement d’une connexion. Contrairement à l’émission de datagrammes, les messages sont reçus en mode flot (pas de notion de frontière de message) Modèle de communication : - le serveur est en attente d’une demande de connexion sur un numéro de port TCP correspondant à un service via un socket. - lorsqu’une requête arrive le serveur reçoit un signal, il crée un nouveau socket puis se duplique (fork()). - le processus fils prend en charge l’échange de données avec le client (exec()), tandis que le processus père retourne attendre de nouvelles demandes de connexion sur le premier socket.

Communication en mode connecté(2) Primitives associèes au différentes étapes de la communication : Création et attachement du socket Socket/bind Ouverture du service listen Attente de la demande de connexion accept Création d’un processus fils fork Traitement de la demande exec processus père processus fils

Listen( ) Après avoir créé un socket de type SOCK_STREAM, le serveur indique au système qu’il est à l’écoute sur un port TCP socket (AF_INET, SOCK_STREAM, 0); int listen ( sock, nb ) int sock; /* descripteur du socket d’écoute */ int nb; /* nombre maxi de connexions */ => si le champ sin_port de la structure sockaddr_in n’a pas été initialisé, le numéro de port est attribué par le système. Le processus utilisera getsockname() pour le connaître

Accept() Accept() permet d’extraire une demande de connexion parmi l’ensemble des requêtes en attente (FIFO) La primitive crée un nouveau socket qui est associée à un nouveau numéro de port choisi par le système et retourne son descripteur Au retour de l’appel, le champ p_adr->sin_port contient le numéro de port du socket du client ayant demandé l’ouverture d’une connexion int accept ( sock, p_adr, p_lgadr ) int sock; /* descripteur du socket */ struct sockaddr *p_adr; /* adresse du socket */ int *p_lgadr; /* pointeur sur la longueur de l’adresse */ => s’il n’y a pas de requête en attente l’appel est bloquant sauf si le socket est en mode non bloquant (cf. fcntl). En ce cas, la valeur de retour vaut –1 et errno = EWOULDBLOCK

Communication en mode connecté : côté client Etapes d’une demande d’établissement de connexion : Création et attachement du socket Socket/bind Construction de l’adresse du serveur Demande de connexion connect Echec Dialogue avec le serveur

Connect( ) La primitive connect() réalise l’établissement d’une connexion bidirectionnelle de bout-en-bout entre le client et le serveur en associant socket serveur et socket client. int connect ( sock, p_adr, lgadr ) int sock; /* descripteur socket local */ struct sockaddr *p_adr; /* adresse socket distant */ int lgadr; /* longueur adresse distante */ => socket local et distant doivent être de même type et appartenir au même domaine. => le serveur doit avoir effectué un listen() et ne pas avoir atteint la file de demandes de connexion en attente ne doit pas être pleine.

Connect( ) : délai d’établissement d’une connexion Lorsque la file de demandes de connexions du serveur est pleine, le processus client est bloqué jusqu’à expiration du délai d’établissement d’une connexion. Le code de retour est alors –1 et errno = ETIMEDOUT En mode non bloquant, le retour est immédiat mais la tentative d’établissement de connexion est maintenue : - le client peut s’enquérir de l’établissement de la connexion avec select( ) en passant le descripteur du socket parmi les paramètres représentant les descripteurs testés en écriture. - s’il exécute à nouveau un connect avant expiration du délai d’établissement, le retour est immédiat et errno = EALREADY

Emission/Réception de messages TCP(1) Les primitives standard de lecture/écriture de fichiers permettent de lire/écrire dans les sockets, donc d’envoyer des messages TCP int write ( sock, msg, lg ) int sock; /* descripteur du socket local */ char *msg; /* adresse du message */ int lg; /* longueur du message */ int read ( sock, msg, lg ) char *msg; /* adresse de sauvegarde du message */ int lg; /* longueur de la zône */

Emission de messages TCP(2) La primitive send permet l’envoi de données urgentes (hors bande) int send (sock, msg, option) int sock; /* descripteur du socket local */ char *msg; /* adresse du message à envoyer */ int lg; /* longueur du message */ int option /* 0 ou MSG_OOB */ => retourne le nombre de caractères émis la lecture est bloquante si le buffer en émission (socket local) ou le buffer en réception (socket distant) est plein fcntl( ) permet les lectures non bloquantes

Réception de messages TCP(3) La primitive recv permet d’extraire des données urgentes et de lire des données sans les extraire du buffer de réception du socket int recv ( sock, msg, lg, option ) int sock; /* descripteur du socket local */ char *msg; /* adresse de sauvegarde du message */ int lg; /* longueur de la zone */ int option; /* 0 ou MSG_PEEK ou MSG_OOB */ => La lecture est par défaut bloquante. Le paramètre lg spécifie un nombre maximal de caractères à lire.

Terminaison d’une connexion Au lieu d’utiliser la primitive close sur le descripteur du fichier comme pour les sockets UDP, il faut utiliser la primitive shutdown qui assure le transfert des messages en attente d’émission dans les buffers locaux int shutdown ( desc, sens ) int desc; /* descripteur de socket */ int sens; /* 0, 1 ou 2 */ 0 indique que le processus ne veut plus recevoir, 1 qu’il ne veut plus émettre et 2 ni recevoir, ni émettre si un processus tente d’écrire sur un socket qui a été fermé en reception sur le site distant, il reçoit le signal SIGPIPE

Signaux SIGIO/SIGURG Le signal SIGIO peut être envoyé par le système à un ou plusieurs processus lorsqu’un message a été reçu sur un socket : - définir un handler du signal SIGIO (ie. fonction de traitement du signal) - demander l’envoi du signal SIGIO à l’arrivée d’un caractère (fcntl(), FASYNC) - attribuer un groupe propriétaire au socket (fcntl(sock), F_SETOWN, getpid()) De même le signal SIGURG peut être envoyé à un groupe de processus lors de la réception d’un caractère urgent (utiliser recv et l’option MSG_OOB); celui-ci est repéré dans le flot de données par une marque

Paramétrage des sockets (1) La primitive getsockopt fournit des informations sur le paramétrage int getsockopt ( desc, niveau, option, o_arg, lg) int desc; /* descripteur de la socket */ int niveau; /* niveau de l’option */ int option; /* option à appliquer */ char *p_arg; /* pointeur pour récupérer la valeur */ int *lg; /* à l’appel : lg réservée, au retour lg du résultat */ => Quand les options sont définies au niveau de l’interface des sockets, la valeur du paramètre option est SOL_SOCKET (pour que la prise en compte des options ait lieu a un autre niveau, utiliser getprotobyname())

Paramétrage des sockets (2) Modification de la valeur d’une option : int setsockopt (desc, niveau, option, p_arg,lg) int desc; /* descripteur du socket */ int niveau; /* niveau de l’option */ int option; /* option à appliquer */ char *p_arg; /* pointeur sur l’argument de l’option */ int lg; /* longueur de l’argument */

Paramétrage des sockets (3) Valeurs possibles de certaines options <sys/socket.h> SO_TYPE type de la socket (getsockopt seulement) SO_BROADCAST si *p_adr=1 diffusion (SOCK_DGRAM seulement) SO_SNDBUF *p_adr = taille du buffer d’émission SO_RCVBUF *p_adr = taille du buffer de réception

Source « La communication sous UNIX » Jean-Marie RIFFLET, édition Mc Graw Hill