Vous êtes sur la page 1sur 18

Les Sockets

Les sockets sont un moyen de communication interprocess typique des systmes d'exploitation UNIX BSD. Elles offrent l'avantage par rapport aux IPC Systme V de permettre des communications entre des machines diffrentes. Les sockets sont un modle gnral pour implanter un nombre indfini de types de communications et divers protocoles.

Vu de l'extrieur la socket est un descripteur de fichier. Ce sont les trois paramtres de l'appel systme socket() qui permettent de crer une socket de type appropri.

La notion de domaine
Diffrents types de sockets auront des noms et des proprits de communication diffrentes. On distingue diffrents domaines d'adressage. Le premier paramtre de l'appel systme socket() dfinit le domaine auquel appartient la socket. C'est une constante symbolique dfinie dans /usr/include/sys/socket.h. On parle aussi pour ce champ, d'adresse format (d'o le prfixe AF_ des constantes dfinies dans le fichier header). Ce terme de format convient bien puisque ce paramtre de l'appel socket() dtermine directement le format des deux paramtres suivants. Les domaines couramment supports sont : * AF_UNIX domaine UNIX (une seule machine). * AF_INET domaine Internet (des machines distinctes).

@ socket

@ internet + n port

Il s'agit des sockets du domaine Internet. Pour le domaine UNIX, les sockets sont reprsentes par des noms de fichier UNIX.

Vu du processus la socket est manipule comme un descripteur. P1 doit connatre sa socket et celle de P2 pour communiquer.

P1

P2

Types et Protocoles
Le second paramtre de l'appel socket() dfinit le type de communication. Les types courramment supports sont SOCK_STREAM et SOCK_DGRAM. Pour chaque type, un protocole est attach par dfaut en attribuant la valeur 0 au troisime paramtre de l'appel socket(). Socket connecte Les sockets Internet de type socket stream utilisent par dfaut le protocole TCP/IP (circuit virtuel). Socket non connecte Les sockets Internet de type non connect utilisent par dfaut le protocole UDP/IP (datagramme).

P1 peut manipuler sa propre socket partir du descripteur et doit construire l'@ de la socket distante partir de l'@ internet de P2 et du n de port choisi. Chaque client doit constituer l'@ de la socket serveur et constituer sa propre @ pour l'envoyer au serveur. Le serveur constitue sa propre @.

Modle SOCKET

processus client

processus serveur

couche socket couche protocole TCP ou UDP IP couche physique Driver ethernet

couche socket couche protocole TCP ou UDP IP couche physique Driver ethernet

RESEAU

Socket en mode datagramme (UDP)


Un processus souhaitant mettre un message destination d'un autre processus, doit d'une part disposer d'un point de communication local (descripteur de socket sur le systme local) et d'autre part connatre une adresse sur le systme auquel appartient son interlocuteur (en esprant que son interlocuteur dispose d'une socket attache cette adresse ...). A chaque requte, le client doit donner l'adresse du serveur. Une requte est constitue d'un seul paquet. Pas de notion de contrle de bout en bout. Un paquet de requte peut ne pas parvenir au serveur. De mme, un paquet de rponse peut ne pas parvenir au client. Il est donc ncessaire de fournir au dessus d'UDP/IP une couche logicielle pour en faire un service fiable (ex. : NFS). Les sockets de ce type sont utilises en mode non connect : toute demande d'envoi d'un message doit comporter l'adresse de la socket destinataire.

La structure

sockaddr_in

C'est par l'intermdiaire de cette structure qu'il sera possible de dsigner un service sur une machine particulire. struct sockaddr_in { short sin_family;

/* la famille de l'@ : AF_INET */ u_short sin_port; /* le numro de port */ struct in_addr sin_addr; /* l'@ Internet */ };

L'adresse Internet d'une machine est dans la structure sin_addr struct sin_addr { u_long s_addr; };

La structure hostent correspond une entre dans le fichier /etc/hosts. L'appel la fonction gethostbyname renvoie une structure hostent contenant l'adresse Internet (IP) du serveur dont le nom est pass en paramtre :

struct hostent *gethostbyname (nom) char *nom;

struct hostent { char *h_name; /* nom officiel de la machine */ char **h_aliases; int h_addrtype; int h_length; /* liste d'alias */ /* type d'@ : AF_INET */ /* lg de l'@ */

char **h_addr_list; /* liste d'@ */ #define }; h_addr h_addr_list [0] /* la 1re @ de la liste */

Les oprations d'envoi et de rception


La primitive sendto
Cette primitive permet d'mettre un message vers une socket distante. int sendto ( sock, msg, lg, option, p_dest, lgdest) int sock; /* descripteur de la socket d'mission */ 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 @ socket destinataire */ int lgdest; /* longueur de l'@ de la socket destinataire */ Seules les erreurs dtectes sont locales. Ainsi il n'y a aucune dtection qu'une socket distante est l'adresse donne. Cela signifie que si un message est mis destination d'une machine existante sur un port non associ une socket, le message sera perdu et l'expditeur n'en sera pas avis. Il existe la primitive sendmsg qui permet en un seul appel systme, l'envoi de plusieurs messages.

La primitive recvfrom
int recvfrom ( sock, msg, lg, option, p_exp, p_lgexp) int sock; /* descripteur de la socket de rception */ char *msg; /* adresse de rcupration du message reu */ int lg; /* taille de l'espace allou l'adresse msg */ int option; /* = 0 ou MSG_PEEK pour une simple consultation */ struct sockaddr *p_exp; /* pour rcuprer l'@ d'expdition */ int *p_lgexp; /* taille espace rserv p_exp et longueur du rsultat */

Cette primitive permet un processus d'extraire un message sur une socket dont il possde le descripteur. Pour qu'il y ait un message, il faut naturellement que cette socket ait t lie une adresse et qu'un processus ait envoy un message aprs que cette liaison ait eu lieu. L'appel est bloquant tant qu'il n'y a pas de message sur la socket. La primitive recvmsg permet de raliser une srie de rception de messages.

Serveur
1. cration de la socket : appel systme socket() 2. construction de l'adresse de la socket 3. liaison de l'adresse de la socket la socket : appel systme bind 4. boucle de traitement attente de la requte : appel systme recvfrom traitement : appel systme sendto

Client
1. cration de la socket : appel systme socket() 2. construction de l'adresse de la socket serveur : appel systme gethostbyname 3. s'il attend une rponse du serveur, construction de sa propre adresse et liaison avec la socket locale (bind) 4. envoi de la requte : appel systme sendto 5. s'il y a rponse, traitement de la rponse : appel systme recvfrom

Ct serveur
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define PORT_SERVEUR 11214 /* nbre quelconque > 1024 */ int socketServeur; struct sockaddr_in addrServeur, addrclient; /* structure socket, domaine Internet */ ... Cration de la socket socketServeur = Socket (AF_INET, SOCK_DGRAM, 0) ; domaine : AF_INET, autre domaine AF_UNIX type : SOCKDGRAM (UDP) ou SOCK_STREAM (TCP connect) protocole : 0 (UDP par dfaut) Une valeur de descripteur (de mme nature qu'un file descriptor) est retourne (le plus petit libre).

Construction de l'@ de la socket // mettre tous les paramtres 0 : memset((void *)&addrServeur, 0, sizeof(addrServeur)); // n de port addrServeur . sin_port = PORT_SERVEUR; // @ hote addrServeur . sin_addr . s_addr = INADDR_ANY; /* Internet*/ UNADDR_ANY; /* Unix */ * domaine addrServeur . sin_family = AF_INET; Liaison de l'@ socket la socket bind(socketServeur, (struct sockaddr *)&addrServeur, sizeof(addrServeur)); descripteur de socket : socketServeur, adresse : &addrServeur, taille de la structure : sizeof(addrServeur). Dans le domaine UNIX , l'@ est une structure sockaddr_un qui doit tre renseigne avant le bind. Boucle de traitement int taille = sizeof(addrclient); recvfrom(socketServeur, (char*)&req, sizeof(req), 0, (struct sockaddr*)&addrclient, &taille); /* cette instruction est bloquante en attente de rponse */ sendto(socketServeur ...);

Ct client
C'est le mme principe que pour le serveur. Construction de l'@ de la socket serveur /* nom de la machine et n de port du serveur */ /* il faut connatre le numro de port sur lequel on va se brancher sur le serveur. Par contre on rcupre l'@ du serveur via son nom que l'on doit connatre et la primitive gethostbyname */ struct hostent *hp; if (( hp = gethostbyname(argv[1])) == NULL) { perror ( gethostbyname ); exit (1); } /* o argv[1] est gal au nom de la machine du serveur */ memset((void*)&addrServeur, 0, sizeof (struct sockaddr_in)); // raz des paramtres memcpy((void*)&addrServeur.sin_addr, hp>h_addr, hp>h_length); // copie d'une zone mmoire addrServeur.sin_family = AF_INET; addrServeur.sin_port = PORT_SERVEUR;

Socket en mode stream (TCP) mode connect


C'est le mode de communication utilis par des applications standard de la famille Internet telles que telnet ou ftp ou des applications UNIX telles que rlogin. Il apporte la fiabilit des changes d'information au prix d'un accroissement de leur volume. Pour utiliser ce mode il faut tablir une connexion (un circuit virtuel) entre deux points. Contrairement au mode non connect dans lequel l'un ou l'autre des intervenants peut tre l'initiateur du dialogue, l'un des deux processus (en position de client) demande l'autre (en position de serveur) s'il accepte une communication. On retrouve l'analogie avec le tlphone. Les caractristiques importantes de ce mode sont :

la fiabilit,

l'aspect continu de l'information (flot) ; le rcepteur n'a pas la possibilit de retrouver la structure de l'information envoye.

Serveur
1. cration (socket) et attachement (bind) de la socket d'coute 2. ouverture du service d'coute (listen), cration d'une file d'attente de requtes en attentes sur une socket 3. attente (bloquante) de demande de connexion (accept) et cration en sortie d'une socket de travail 4. cration d'un sous-processus (fork) le pre se branche en attente (3.) le fils traite la demande sur la socket de travail (read et write)

Client
1. cration (socket) et attachement (bind) de la socket client 2. construction de l'adresse de la socket serveur : appel systme gethostbyname 3. demande de connexion (connect) 4. en cas de russite dialogue avec le serveur (read et write).

Ct Serveur
CREER une FILE d'ATTENTE de REQUETES int listen (sd, n); int sd; int n; avec sd : numro du descripteur de socket (socket d'coute) n : nombre maximum de connexions simultanes possibles dans la file d'attente. ACCEPTER une CONNEXION Le dialogue avec un client sera maintenu sur un descripteur diffrent de celui qui a permis la connexion. On obtient ce nouveau descripteur (retour d'appel) avec la primitive accept : int accept (sd, nom, taille); int sd; /* ancien descripteur de socket */ struct sockaddr *nom; /* paramtre de retour */ int taille; /* taille de la structure */ A partir de ce moment le contact est tabli et le dialogue pourra tre effectu l'aide de read() et write().

Ct Client
CONNEXION DU CLIENT Cette connexion est ralise par l'appel connect(). Une fois tablie, la connexion est maintenue. Le dialogue se fait avec les appels read() et write(). int connect (sd, nom, taille); int sd; struct sockaddr *nom; int taille; On associe la socket locale (sd) une destination loigne (serveur) via la structure nom. La socket correspondante du serveur tant bloque en attente de connexion.

Vous aimerez peut-être aussi