|
|
Éléments d'architecture
client-serveur
(Corrigés)
Exercice 1 : M. et Mme...
Dans cet exercice, on se propose d'écrire un serveur de "M.
et
Mme"
:
- Le client lit, sur sa ligne de commande, le nom de
famille
de "M.
et
Mme". Il l'envoie au serveur.
- Le serveur cherche ce nom de famille dans le fichier mEtMme.txt :
- s'il le trouve, il renvoie le nom du fils, de la
fille ou
bien
des
enfants
- sinon il renvoie le message
"Désolé, je ne
le
connais
pas"
- Le client affiche le message reçu du
serveur.
Préparation
Se placer dans un répertoire de travail
tar xvfz q1.tgz
cd Q1
Question 1.1
Le code qui vous est fourni dans le répertoire Q1 comprend
un client et un serveur qui fonctionnent comme dans l'exemple fourni en
cours sur les files de messages :
- concernant le client :
- il crée une file de message
dont
le nom est suffixé par son "pid" (de manière à ne
pas
interférer
avec d'autres clients potentiels) ;
- il se "connecte" au serveur via la file de messages "/client-serveur" (créée
par le serveur) ;
- la requête du client contient non
seulement le "M. et
Mme"
cherché,
mais aussi le nom de la file de messages a
été
créée
en 1.1 par le client et sur laquelle le client attend la
réponse du
serveur ;
- concernant le serveur :
- sur réception d'une requête
client, le serveur
cherche
dans le fichier une ligne qui commence par le "M. et Mme"
mentionné
dans la requête ;
- s'il la trouve, il renvoie l'ensemble de la ligne
sur la file de messages
mentionnée dans la requête ;
- sinon, il renvoie "Desole, je
ne le connais
pas".
Programmer le serveur de sorte qu'il crée un thread à
chaque
fois
qu'il reçoit une requête. Ce thread traite la
requête
et disparaît une fois que la requête est
traitée.
---beginCorr
serveurQ1.1.corrige.c
---endCorr
Question 1.2
Se positionner dans le répertoire parent de Q1.
Taper la commande : cp
-R Q1 Q2
Se positionner dans le répertoire Q2 qui vient
d'être créé.
Dans ce répertoire Q2 (qui reprend le code de la question Q1), adapter le serveur de sorte qu'il
forke 3 threads :
- Chaque thread ouvre le fichier, se met dans le "pool" de threads
en
attente et attend une requête du processus distributeur.
- Sur réception d'une requête, le
serveur retire
le
premier thread du "pool" et lui fait suivre la requête :
- le thread cherche le "M. et Mme" dans le fichier ;
- il répond au client ;
- il se remet dans le "pool" ;
- il attend une requête du processus
distributeur.
Le "pool" de threads peut être implanté
à l'aide :
- d'un tube. Les threads sont en attente de lecture sur ce tube.
Quand le serveur veut leur faire suivre une requête, il
écrit sur ce tube : l'un des threads lit la requête sur le
tube et la traite.
- d'une file de message (même principe que le tube).
- d'un tableau circulaire de requêtes géré via le
paradigme producteur/consommateur, le serveur étant le
producteur et les threads étant les consommateurs.
- de
4
tubes, 3 tubes serveur-thread (1 par thread) et 1 tube threads-serveur.
Quand un thread est prêt à recevoir une requête, il
écrit le descripteur de fichier de son tube serveur-thread dans
le tube threads-serveur. Il se met ensuite en attente de lecture sur ce
tube parent-thread. Quand le serveur reçoit une requête,
il lit un descripteur de fichier de tube parent-thread dans le tube
threads-parent, puis écrit la requête dans ce tube
parent-thread. Le thread lit la requête et la traite.
- toute solution que vous imaginerez et qui fonctionne !
---beginCorr
Le corrigé implante la solution à base d'un tube (cf. serveurQ1.2.corrige.c).
---endCorr
Question 1.3
Se positionner dans le répertoire parent de Q1.
Taper la commande : cp
-R Q1 Q3
Se positionner dans le répertoire Q3 qui vient
d'être créé.
Dans ce répertoire Q3 (qui reprend le code de la question Q1),
programmer le serveur de sorte qu'il forke 26 threads (chacun
étant
chargé des "M. et Mme" commençant par une
certaine lettre
de
l'alphabet) :
- Chaque thread cherche, dans le fichier, la
première
et la
dernière
ligne commençant par sa lettre.
- Sur réception d'une requête, le processus distributeur fait
suivre
la
requête à le thread correspondant à la
1-ère
lettre
du "M. et Mme" :
- le thread ne cherche que dans les lignes qui le
concernent
;
- il répond au client ;
- il attend une nouvelle requête du processus
distributeur.
---beginCorr
serveurQ1.3.corrige.c
---endCorr
Question 4 (non corrigée)
Reprendre le code réalisé à la
question 1 avec les
contraintes
suivantes :
- Le serveur peut forker au maximum 3 threads pour le
traitement
des
requêtes.
- Chacun de ces threads transmet à un thread
spécial
(le
"factureur") un "ticket de facturation" (contenant le pid du processus
demandeur
et le nom de M. et Mme demandé). Cet thread
spécial
écrit
ensuite le ticket dans un fichier texte. La transmission d'information
entre
les threads traitant les requêtes et le "factureur" sera
d'abord
faite
avec un pipe, puis avec une zone de mémoire
partagée.
---beginCorr
A compléter
---endCorr
Exercice 2
Repérer les différentes
architectures
client-serveur
mises en oeuvre dans l'exercice 1.
---beginCorr
Dans l'exercice 1 :
- le code qui est fourni dans le répertoire Q1 utilise une
architecture
"Serveur mono-tâche".
- à la question 1, on utilise une
architecture
"Serveur avec autant de tâches que de clients".
- à la question 2, on utilise une
architecture
"Serveur avec autant
de tâches que de clients" en limitant à 3
(à l'aide
d'un pool de threads) le nombre maximum de tâches à
un instant donné. L'avantage de cette architecture par
rapport
à celle de la question 4 est que les
tâches de
traitement client ne sont pas créées à
chaque
requête client.
- à la question 3, on utilise une
architecture
"Serveur avec N tâches gérant tous les clients", N
étant égal ici à 26.
- à la question 4, on utilise une
architecture
"Serveur avec autant de tâches que de clients" en limitant
à 3 (à l'aide d'un sémaphore) le
nombre maximum de
tâches à un instant donné.
---endCorr
Exercice 3 : M. et Mme... mais avec des enfants
Cet exercice reprend les questions de l'exercice 1, mais en utilisant des enfants au lieu de threads.
Préparation
Se placer dans un répertoire de travail
Vérifier que le tar ci-dessous ne risque pas d'écraser
l'éventuel travail que vous avez fait sur le répertoire
Q1 lors de l'exercice 1.
tar xvfz q1.tgz
cd Q1
Question 3.1
Même fonctionnement qu'à la question 1.1 de l'exercice 1,
sauf que dans cette question 3.1, vous devez programmer le serveur de
sorte qu'il forke un enfant à
chaque
fois
qu'il reçoit une requête. Cet enfant traite la
requête
et disparaît une fois que la requête est
traitée.
---beginCorr
serveurQ3.1.corrige.c
---endCorr
Question 3.2
Se positionner dans le répertoire parent de Q1.
Taper la commande : cp
-R Q1 Q2
Se positionner dans le répertoire Q2 qui vient
d'être créé.
Même fonctionnement qu'à la question 1.2 de l'exercice 1, sauf que dans
cette question 3.2, vous devez travailler avec des processus enfants et pas des threads.
---beginCorr
Le corrigé implante la solution à base de 4 tubes (cf. serveurQ3.2.corrige.c).
---endCorr
Question 1.3
Se positionner dans le répertoire parent de Q1.
Taper la commande : cp
-R Q1 Q3
Se positionner dans le répertoire Q3 qui vient
d'être créé.
Même fonctionnement qu'à la question 1.3 de l'exercice 1, sauf que dans
cette question 3.3, vous devez travailler avec des processus enfants et pas des threads.
---beginCorr
serveurQ3.3.corrige.c
---endCorr
|