Test de rattrapage Réseau : Partie I
(10 mars 2001 – durée : 2h)
M. Laporte - D. Mathieu - C. Pain-Barre
I.U.T. d'Aix en Provence - Département Informatique
Tout document autorisé
Remarques préliminaires :
Sommaire
Introduction
Serveur_connecté_concurrent_monoprocessus
Client connecté
Envoi
et réception de la liste des clients effectifs
Introduction
Dans ce qui va suivre, on suppose que l’on dispose d’un réseau ne permettant pas la multidiffusion matérielle. C’est un réseau point à point structuré en étoile c’est à dire qu’il y a une machine hôte placée au centre de la structure à laquelle sont reliées toutes les autres. Celles-ci ne sont pas reliées entre-elles et ne peuvent donc communiquer qu’avec l'hôte central.
Objectif : service d’acheminement de messages
Le but de cet exercice est d’utiliser cette étoile pour simuler un bus par logiciel, en utilisant une structure client-serveur.
Tout client référencé pourra parler à tout autre client référencé et la multidiffusion sera aussi possible. Pour cela, il faut réaliser un serveur qui devra acheminer tout message en provenance d’un client i et à destination d’un client j ou de tous les clients.
Tout client désireux d’envoyer ou de recevoir des messages doit :
-
d’abord se connecter au serveur et
-
lui communiquer son
pseudo (8 caractères maxi). En réalité,
il envoie la totalité du vecteur (9 octets) contenant le pseudo,
le caractère '\0' inclus.
Puis, pour émettre un message à destination
d’un client quelconque, il doit demander le service au serveur en lui envoyant
un message contenant dans l'ordre les éléments suivants :
-
le "numéro du client" destinataire du message (entier court non
signé) ;
-
la taille en octets (entier court non signé) du message à
transmettre ;
-
le message à transmettre.
En théorie, le bus formé peut contenir 65536 clients mais
deux numéros ont un rôle particulier et sont réservés
:
-
le numéro 0 désigne le serveur ;
-
le numéro 65535 désigne tous les clients ; il est
utilisé pour demander une multidiffusion.
Gestion de la connexion d'un client
Le serveur doit gérer la table TabClients
référençant
chaque client, et définie comme suit :
namespace
{
struct SClient
{
bool EstConnecte;
char Pseudo [9];
}; // SClient
enum {CstMaxBus
= 65534};
SClient TabClients
[CstMaxBus];
} // namespace anonyme |
Le serveur attribue à tout client qui se connecte
un élément de cette table dont l'indice est calculé
par sdComm - sdConnect où sdComm est
le résultat de la fonction accept(), et sdConnect
est le socket descriptor de la socket de connexion. Cet indice
correspond au "numéro de client".
Le champ EstConnecte
est mis à vrai dès que le client se connecte, mais celui-ci
ne fait effectivement partie de la liste que lorsque le serveur
a reçu son pseudo et a renseigné la donnée
membre Pseudo. Un tel client est appelé un client effectif.
Le serveur envoie cette liste à tous les clients
effectifs dans l'un des deux cas suivants :
-
un client devient effectif,
-
un client est déconnecté (voir plus bas).
Message en provenance d'un client
Lorsque le serveur reçoit un message en provenance
d'un client, il examine sa destination :
-
si le destinataire est le serveur lui-même (numéro de client
= 0), il s'agit d'une trame qui contient un pseudo, ou,
lorsque la taille du message est nulle, une demande de la liste des clients
effectifs,
-
si le destinataire est inconnu, il doit le signaler à l’émetteur,
-
sinon, il s'agit d'un message à transmettre. Dans la trame, il remplace
le numéro du destinataire par celui de l'émetteur puis il
l'envoie
-
s'il s'agit d'une multidiffusion (le destinataire était 65535),
à tous les clients effectifs sauf à l'émetteur,
-
sinon, au destinataire.
Remarque : tous les objets globaux utilisés devront être
déclarés dans l'espace de noms anonyme.
Serveur connecté
concurrent monoprocessus
-
Liste des fichiers créés ou modifiés : exo_01s.cxx.
Ecrire une fonction ppal() qui contient la
modélisation d'un serveur connecté concurrent monoprocessus
qui :
-
crée une socket internet en mode connecté, et la lie
au port
65001 ;
-
appelle la fonction InitClients (void) qui initialise les données
nécessaires à la gestion des clients (TabClients,
…) ;
-
dans une boucle infinie, attend au moyen d'un appel à Select()
:
-
soit une information en provenance d'un client auquel cas elle appelle
TraiterInfoDuClient
(int sd) qui prend en paramètre le descripteur sur lequel est
arrivée l'information ;
-
soit une demande de connexion d'un client, auquel cas elle appelle TraiterConnexion(void);
-
renvoie 0.
Les fonctions InitClients(), TraiterInfoDuClient(),
TraiterConnexion()
mettent à jour la variable Mask nécessaire pour
utiliser la fonction Select().
Remarque : les fonctions InitClients(), TraiterInfoDuClient()
et
TraiterConnexion() ne sont pas à écrire
pour le moment.
Corrigés : exo_01s.cxx
Sommaire
Client connecté
-
Liste des fichiers créés ou modifiés : exo_01c.cxx.
Ecrire une fonction ppal() qui :
-
se connecte au serveur dont l'adresse et le port sont passés en
premier et deuxième argument de la commande ;
-
déroute le signal SIGINT qui permet de sortir de la boucle
ci-dessous,
-
dans une boucle, attend :
-
soit que l'utilisateur saisisse quelque chose au clavier, auquel cas il
appelle TraiterClavier (void) ;
-
soit qu'une information en provenance du serveur lui parvienne, auquel
cas il appelle TraiterInfoDuServeur (void) ;
-
lorsque la sortie de boucle a été décidée par
le client, celui-ci doit :
-
signaler [1] au serveur qu'il veut être
déconnecté;
-
traiter tous les messages en provenance du serveur jusqu'à ce que
le serveur rende effective la déconnexion.
-
retourne 0.
A nouveau, les fonctions TraiterClavier() et
TraiterInfoDuServeur()
ne sont pas encore à écrire.
[1] "signaler" veut dire indiquer au serveur qu'il
ne lui enverra plus de message.
Corrigés : exo_01c.cxx
Sommaire
Envoi
et réception de la liste des clients effectifs
Envoi de la liste des clients par le serveur
Dans l'espace de noms anonyme, écrire la fonction
de prototype :
void EnvoyerListe (int sd); |
qui est appelée par le serveur lorsqu'il doit envoyer la liste
des clients effectifs au client connecté à la socket
sd.
Cette fonction :
-
envoie l'annonce du début de liste composée :
-
du "numéro du serveur" (entier court non signé à 0),
et
-
du caractère L (comme Liste),
-
parcourt le tableau TabClients. Pour chaque client effectif de
la table, c'est à dire connecté et identifié (EstConnecte
est vrai et le
pseudo est renseigné), elle envoie :
-
le "numéro du client" (son indice dans le tableau, entier court
non signé),
-
les 9 octets du pseudo.
-
envoie le "numéro du serveur" (entier court non signé à
0) annonçant la fin de liste.
Réception de la liste des clients effectifs par le client
Dans l'espace de noms anonyme, écrire
la fonction de prototype :
void RecevoirListe (int sd); |
qui est appelée par le client lorsqu'il a reçu l'annonce
du début de liste, et qui affiche les informations recueillies.
Sommaire

© D. Mathieu mathieu@romarin.univ-aix.fr
I.U.T.d'Aix en Provence - Département Informatique