1 Les sockets UNIX Sylvie Dupuy [email protected] année 2000.

41
1 Les sockets UNIX Sylvie Dupuy [email protected] année 2000

Transcript of 1 Les sockets UNIX Sylvie Dupuy [email protected] année 2000.

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

1

Les sockets UNIX

Sylvie Dupuy

[email protected]

année 2000

Page 2: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

2

Protocoles de l’Internet : rappels

Interface du service de transport

PHY 1 PHY 1 PHY 2 PHY 2

ARP

MAC 1MAC 2

Data Link 1

MAC 1MAC 2

Data Link 2Data Link 2Data Link 1

ARP ARP

ICMP

IP IP

ICMP

IP

ICMPTCP UDPUDP TCP

Num. port UDP ou TCP

APPLICATION APPLICATION

Numéro de port = identifie l’application à laquelle le paquet IP est destiné

send receive

Routeur IP

Endsystem sur réseau 1 Endsystem sur réseau 2

Page 3: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

3

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

Page 4: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

4

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 …

Page 5: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

5

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.

Page 6: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

6

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 filss’exécutent simultanément (en temps partagé ou bien en parallèle

surun système multiprocesseurs)

=> le processus fils hérite du contexte d’exécution du processus père

Page 7: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

7

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)

Page 8: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

8

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)

Page 9: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

9

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

Page 10: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

10

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

Page 11: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

11

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

Page 12: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

12

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 */

};

Page 13: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

13

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] */

};

Page 14: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

14

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

Page 15: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

15

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’émissionpointeurs sur les données en émission/réceptiongroupe de processus pour la gestion des signaux SIGURG, SIGIO

Page 16: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

16

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).

Page 17: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

17

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)

Page 18: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

18

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

Page 19: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

19

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)

Page 20: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

20

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.

Page 21: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

21

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 */ };

Page 22: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

22

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

Page 23: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

23

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;

Page 24: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

24

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 ( )

Page 25: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

25

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.

Page 26: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

26

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.

Page 27: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

27

Communication en mode connecté(2)

Primitives associèes au différentes étapes de la communication :

Création et attachement du socketSocket/bind

Ouverture du servicelisten

Attente de la demande de connexionaccept

Création d’un processus filsforkprocessus père

Traitement de la demandeexec

processus fils

Page 28: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

28

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

Page 29: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

29

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

Page 30: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

30

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 connexionconnect

Echec

Dialogue avec le serveur

Page 31: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

31

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.

Page 32: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

32

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

Page 33: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

33

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 )int sock; /* descripteur du socket local */char *msg; /* adresse de sauvegarde du message

*/int lg; /* longueur de la zône */

Page 34: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

34

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

Page 35: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

35

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.

Page 36: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

36

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

Page 37: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

37

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

Page 38: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

38

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())

Page 39: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

39

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 */

Page 40: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

40

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

Page 41: 1 Les sockets UNIX Sylvie Dupuy sdupuy@ccr.jussieu.fr année 2000.

41

Source

« La communication sous UNIX »

Jean-Marie RIFFLET, édition Mc Graw Hill