Nous allons donc faire un tour de code de notre serveur TCP avec multiplexage pour que vous puissiez voir que nous allons commencer par la fonction
principale et que toute la fonctionnalité du serveur TCP est implémentée à l'intérieur de la fonction de configuration de la communication
du serveur TCP.
Entrons donc dans cette fonction et voyons ce que nous y avons implémenté.
C'est vrai.
Vous connaissez donc déjà la conception et la mise en œuvre d'un serveur TCP.
Je vais donc passer rapidement sur les étapes que nous avons déjà abordées dans la discussion sur la conception
précédente du serveur TCP.
Il s'agit donc de la phase d'initialisation au cours de laquelle nous allons initialiser toutes
les variables que nous devrons utiliser dans la mise en œuvre de ce serveur Dhcp.
Et ici, nous avons pris notre structure de données qui stockera les descripteurs de fichiers de communication de tous
les clients connectés, n'est-ce pas ?
Et pour stocker les informations relatives au serveur et au client, à savoir l'adresse IP et le numéro
de port, nous avons à nouveau pris les deux structures suivantes : ADR underscore serveur et ADR underscore client.
C'est vrai.
Que fait maintenant le serveur TCP ?
La toute première chose que fait ce serveur Dhcp est d'initialiser, de surveiller, de souligner,
de définir.
Voyons donc ce que fait cette fonction.
Vous pouvez donc voir qu'il s'agit de la mise en œuvre de cette fonction.
Cette fonction ne fait donc rien, elle initialise simplement le tableau des descripteurs de fichiers surveillés à moins
un.
Moins un est ici.
Moins un représente l'absence de descripteur de fichier de communication dans ce tableau.
Vous vous souvenez que lorsque nous avons discuté de la conception de haut niveau, notre serveur TCP maintenait ce
tableau, qui.
qui a été utilisé pour stocker le descripteur de fichier de communication ainsi que le descripteur de fichier de socket maître.
C'est donc de ce tableau qu'il est question ici.
Ce tableau est appelé.
Appelons donc ce tableau "ensemble de descripteurs de fichiers surveillés".
Nous avons donc initialisé ce tableau avec moins un, ce qui signifie qu'à ce stade, le serveur
n'a pas de descripteur de fichier à surveiller.
C'est vrai.
Nous venons donc d'initialiser ce tableau dans cette fonction.
C'est vrai.
La deuxième chose que fait le serveur Dhcp est de créer un descripteur de fichier de socket principal, n'est-ce pas ?
Nous en avons déjà parlé.
Le serveur TCP utilise ensuite la structure server underscore addr pour spécifier ses propres informations d'identification.
Il s'agit de son numéro de port TCP et de son adresse IP.
Dans un troisième temps, le serveur TCP appelle l'appel système bind, qui lui permet de communiquer au système
d'exploitation sous-jacent le type de paquet ou de serveur TCP qui l'intéresse.
Notre serveur TCP souhaite donc recevoir un paquet dont le numéro de port de destination dans l'en-tête
de transport est égal au numéro de port du serveur.
L'adresse IP spécifiée dans l'en-tête du paquet est égale à l'adresse IP de n'importe quelle interface locale de
cette machine serveur.
C'est vrai.
Ces étapes ne sont donc pas différentes de celles dont nous avons discuté dans le.
Discussion sur le serveur TCP précédent.
Ce sont exactement les mêmes.
Ensuite, il y a un appel au système de leçons.
C'est vrai.
À ce stade, c'est-à-dire à la ligne 136, le serveur TCP a créé un descripteur de fichier, appelé descripteur
de fichier de la socket principale.
Ainsi, dès que notre serveur crée un nouveau descripteur de fichier, qu'il s'agisse d'un descripteur de fichier de la socket
principale ou d'un descripteur de fichier de communication, il doit ajouter ce descripteur de fichier à ce tableau.
C'est vrai.
Nous avons donc appelé cette fonction add to monitor file descriptor set et nous avons passé le descripteur de fichier que le serveur
a créé, c'est-à-dire le descripteur de fichier de la socket principale.
Cette fonction permet donc d'ajouter le descripteur de fichier de la socket maître au tableau.
Entrons donc dans cette fonction et voyons ce qu'il en est.
Vous pouvez donc constater que la mise en œuvre de cette fonction est relativement, très simple.
Nous itérons sur le tableau et dès que nous trouvons un emplacement vide dans le tableau, qui est représenté
par la valeur moins un dans cet emplacement particulier, nous ajoutons le descripteur de fichier qui doit être surveillé à ce tableau.
C'est vrai.
La mise en œuvre est donc simple.
Ainsi, avant d'entrer dans la boucle while one, notre serveur TCP a démarré et a créé un descripteur de fichier
de socket principal et a ajouté le descripteur de fichier de socket principal à ce tableau.
Vous pouvez donc voir ici que notre serveur TCP est ici et qu'il est sur le point d'entrer dans la boucle while pour faire un appel à l'appel système
select afin qu'il puisse surveiller le descripteur de fichier qu'il est censé surveiller.
Vous pouvez donc voir que dès que le serveur entre dans la boucle infinie, il ré-initie la lecture de l'ensemble des données.
Que fait cette fonction ?
Cette fonction ne fait rien.
Il crée simplement un clone ou une copie de ce tableau de descripteurs de fichiers surveillés et il copie ce tableau dans le jeu de lecture
parce qu'en fin de compte, pour le système de sélection, la structure de données que vous
devez passer est le jeu de lecture.
Ainsi, votre jeu de lecture doit être exactement le clone ou la copie de votre tableau de descripteurs de fichiers surveillés.
C'est donc la fonction re init read set qui fait ce travail.
Voyons donc la mise en œuvre de cette fonction : que fait-elle ?
Cette fonction ne fait donc rien d'autre que de vider le jeu rouge que vous lui avez passé en
argument, puis de parcourir le tableau des jeux de descripteurs de fichiers surveillés.
C'est vrai ?
Et pour tous les descripteurs de fichiers présents dans ce tableau, il suffit de copier tous ces descripteurs de
fichiers du tableau vers le jeu rouge.
Cette fonction crée donc une copie ou un clone de l'ensemble de descripteurs de fichiers surveillés dans
l'ensemble rouge.
En effet, le tableau des descripteurs de fichiers surveillés contient tous les descripteurs de fichiers surveillés
à tout moment par notre serveur TCP.
Ces descripteurs de fichiers doivent également être présents dans l'ensemble.
C'est vrai.
Ainsi, après avoir copié et rempli l'ensemble de lecture avec les descripteurs de fichiers requis.
Il est maintenant temps pour notre serveur TCP de lancer l'appel système select.
Vous pouvez donc voir que l'appel système select a été appelé sur le jeu de lecture, qui contient tous les descripteurs
de fichiers à surveiller.
Mais à ce stade, notre serveur TCP n'a qu'un seul descripteur de fichier dans ce jeu de lecture, qui est le descripteur de fichier
de la socket principale, et il n'a pas de descripteur de fichier de communication pour l'instant parce qu'aucun
client ne s'est encore connecté à notre serveur TCP.
Vous pouvez donc voir dans ce diagramme qu'un serveur TCP a invoqué l'appel système select sur l'ensemble et que notre serveur TCP est
maintenant bloqué dans l'attente d'une demande d'établissement de connexion de la part d'un client.
En ce moment même.
Supposons qu'un client C1 vienne envoyer une demande d'établissement de connexion à notre serveur TCP.
Ainsi, lorsque cela se produit, notre serveur Dhcp est débloqué de l'appel système select et dans le jeu de lecture, le descripteur
de fichier de la socket principale est activé.
C'est vrai.
Nous allons donc vérifier ici que le descripteur de fichier du socket maître est activé dans le jeu de lecture.
Cela signifie que notre serveur a reçu une nouvelle demande de connexion de la part d'un client et qu'il est temps pour notre serveur
d'accepter la connexion et de créer le descripteur de fichier de communication pour ce client particulier.
Vous pouvez donc voir dans ce diagramme que le client C1 envoie la demande d'initiation de connexion au serveur TCP ou que
le serveur TCP invoque l'appel système Accept et crée le descripteur de fichier de communication.
Grâce à ce descripteur de fichier de communication ou au serveur TCP, toutes les communications futures avec le client
C1 seront effectuées.
En ce moment même.
Comme je l'ai expliqué, la conception de haut niveau prévoit que, quel que soit le descripteur de fichier de communication ou le serveur
TCP créé, il doit stocker ce descripteur de fichier de communication dans le tableau de l'ensemble des descripteurs de fichiers surveillés.
C'est vrai.
Il est donc temps d'invoquer cette fonction qui va ajouter au tableau le descripteur de fichier de communication
du client qui vient de se connecter à notre serveur TCP.
C'est vrai.
Nous avons déjà discuté de la mise en œuvre de cette fonction.
Elle ajoute simplement le descripteur de fichier, qui est transmis en tant qu'argument à cette fonction,
dans l'emplacement vide du tableau.
C'est vrai.
À ce stade, le client C1 vient de se connecter à notre serveur TCP et notre serveur TCP a créé le descripteur de
fichier de communication pour ce client.
Et comme je l'ai dit, notre serveur TCP utilisera ce descripteur de fichier de communication pour effectuer tous les échanges
de données avec ce client.
C1 D'accord, et ce descripteur de fichier de communication a été ajouté au tableau, n'est-ce pas ?
Vous pouvez donc le voir dans l'ensemble des données lues à ce stade.
Le descripteur de fichier de la socket principale était déjà présent.
Le descripteur de fichier de communication est maintenant également présent.
C'est vrai.
Rappelez-vous donc que nous ajoutons le descripteur de fichier de communication au tableau et au début
de la boucle while one.
Nous avons copié l'ensemble du tableau sur l'ensemble FDR, de sorte qu'il est aussi bon que vous.
Ajout du descripteur de fichier de communication à l'ensemble FDR.
C'est vrai.
Jusqu'à présent, nous avons vu que le client C1 vient d'arriver et qu'il est connecté à notre serveur.
Notre serveur a créé le descripteur de fichier de communication pour ce client et notre serveur a ajouté ce descripteur
de fichier de communication à l'ensemble FDR.
Par conséquent, l'autre partie ne fonctionnera pas.
Ensuite, nous passerons à la boucle unique, c'est-à-dire que notre serveur retournera maintenant à la boucle while one.
Ainsi, notre serveur réintègre ou réitère la boucle infinie qu'est la boucle while one et appelle le jeu de lecture re init
qui se trouve ici.
Il doit rafraîchir l'ensemble des données lues.
Rappelez-vous que lors de l'itération précédente, le jeu de lecture ne contenait que le descripteur de fichier de la socket principale.
Et maintenant, parce que notre serveur a établi la connexion avec le nouveau client, notre serveur a maintenant deux descripteurs
de fichiers à surveiller.
Le premier est le descripteur de fichier de la socket principale et le second est le descripteur de fichier
de communication du client c one.
Ainsi, le re init read prendra soin de recopier le nouvel ensemble de descripteurs de fichiers à surveiller et à lire correctement,
puis notre serveur se bloque à nouveau au niveau de l'appel système select.
À ce stade, notre serveur surveille la nouvelle demande de données émanant du client C 1, qui est déjà connecté
à notre serveur, et notre serveur est également en mesure de traiter les nouvelles demandes d'établissement de connexion
émanant de nouveaux clients.
Pourquoi ?
Parce qu'il surveille le descripteur de fichier du socket maître ainsi que le descripteur de fichier de communication du client
C one.
Ainsi, la même chose se répète : notre serveur TCP est débloqué de l'appel système select.
Si le client C1 envoie une demande de données au serveur TCP ou si le client C2 envoie une demande d'initiation de connexion
à notre serveur TCP, ce dernier est débloqué si l'un de ces deux événements se produit.
Vous pouvez donc voir ici que si la demande d'établissement d'une nouvelle connexion provient du client C2, cette
condition sera vraie.
Oui, parce que c'est le descripteur de fichier de la socket principale qui sera activé.
C'est vrai.
Et si de nouvelles demandes de données arrivent du client C1 qui est déjà connecté à notre serveur, alors la partie
"else" s'exécutera.
Oui, parce que.
Tout descripteur de fichier autre que le descripteur de fichier du socket maître sera activé.
C'est vrai.
Ainsi, lorsque cette partie est activée, nous devons déterminer quel descripteur de fichier de communication
est activé, car de nombreux clients peuvent être connectés au serveur à un moment donné.
Pour ce faire, nous devons parcourir le tableau des descripteurs de fichiers surveillés et vérifier lesquels.
Le client a envoyé la demande de données à notre serveur, nous pouvons donc le faire en itérant sur le tableau.
Surveiller le tableau de l'ensemble des descripteurs de fichiers et vérifier si un trait de soulignement macro est défini et si ce descripteur de
fichier particulier a été activé dans l'ensemble de lecture.
C'est vrai.
Ainsi, la condition "if" ne sera vraie que pour les descripteurs de fichiers de communication qui sont activés dans
le jeu de lecture.
En ce moment même.
La prochaine chose que le serveur TCP doit faire est de recevoir les données du client dont le descripteur
de fichier de communication est activé et de renvoyer la réponse.
Il s'agit donc à nouveau de la même logique que celle que vous avez déjà apprise dans le serveur TCP précédent.
Préparer le tampon de données.
Recevoir les données du client.
C'est vrai.
Et si le client suppose que le client a envoyé zéro octet de données à un serveur TCP, alors notre serveur TCP peut fermer
la connexion avec ce client.
Dès que notre serveur TCP ferme la connexion avec ce client, il n'a plus besoin de surveiller ce descripteur
de fichier de communication lors des prochaines invocations d'appels système sélectionnés.
C'est la raison pour laquelle nous devons supprimer ce descripteur de fichier de communication de notre tableau de descripteurs
de fichiers surveillés.
Dans le cas contraire, si le client a envoyé des données légitimes à notre serveur TCP pour qu'il les traite, notre serveur
TCP les intégrera dans les données du client.
C'est-à-dire notre serveur TCP.
Il doit savoir dans quel format le client a envoyé les données.
C'est vrai.
Notre serveur TCP additionne simplement les valeurs envoyées par le client, calcule la somme des
deux valeurs et renvoie la réponse au client.
Il s'agit donc de la même logique que celle qui consiste à recevoir la demande du client, à la traiter et à renvoyer
le résultat au client.
Vous pouvez donc voir que toute cette logique se trouve à l'intérieur de cette boucle for.
En d'autres termes, nous vérifions tous les descripteurs de fichiers de communication activés dans l'ensemble et tous les descripteurs de fichiers
de communication activés.
Cela signifie que plusieurs clients ont envoyé des données à notre serveur TCP ou que le serveur TCP traite une à
une les demandes de données de ces clients et renvoie la réponse.
C'est donc toute la logique du multiplexage qui est mise en œuvre dans la partie "else".
Ainsi, en avançant dans ce diagramme, vous pouvez voir si le client C2 a envoyé la demande d'initiation de connexion
à notre serveur TCP.
Notre serveur TCP accepte la connexion.
Nous allons créer un autre descripteur de fichier de communication et nous allons ajouter ce descripteur
de fichier de communication à l'ensemble et il utilisera le descripteur de fichier de communication respectif afin d'effectuer l'échange de données avec les
clients correspondants.
Voici donc le diagramme d'état complet d'un serveur TCP avec multiplexage.
Ce diagramme illustre le fonctionnement d'un serveur TCP doté de capacités de multiplexage.
Vous pouvez donc vous aider de ce code et je vous demande d'écrire votre propre serveur TCP avec multiplexage.
Cela vous donnera une bonne pratique.
Ne vous contentez pas de regarder ce code, sinon vous ne vous sentirez pas à l'aise pour écrire un serveur TCP ou pour programmer
des sockets.
Et téléchargez tous vos codes sur GitHub.
Bien entendu, je partagerai avec vous les chemins d'accès à tous ces codes dans la section des ressources.
Il s'agissait donc d'un serveur Dhcp avec multiplexage.
Ensuite, nous verrons la démonstration du serveur Dhcp avec le multiplexage et nous verrons comment le serveur Dhcp peut
communiquer avec plusieurs clients en même temps.