Architecture N-tiers

 

Master Expert Technologie de l'information EPITECH 2020.

Co-fondateur et CTO d'une startup dans l'Edtech 2019 - fin 2022. (+3 ans)

Formation PSPO-1 Agile Scrum 2022.

Co-fondateur et CTO d'une startup dans la Deeptech fin 2022 - aujourd'hui.

Valentin MONTAGNE

Déroulement du cours

1

Qu'est-ce qu'une architecture N-Tiers ?

3

Création d'une architecture Client / Serveur d'un service IA.

2

Les modes de communications entre processus ?

4

QCM de fin de module et rendu des TPs et exercices

Chaque séance débutera par la présentation d'un concept et de l'intérêt d'utilisation de celui-ci.

1

Théorie

Après la théorie, nous verrons alors la pratique en réalisant des exercices.

2

Pratique

Nous verrons ensemble la correction des travaux pratiques. N'hésitez pas à poser vos questions.

3

Correction

Déroulement des journées

Avez-vous déjà réalisé une architecture Client / Serveur ?

Qu'est-ce qu'une architecture N-Tiers ?

1.

Comment internet fonctionne ?

En 1960, les États-Unis cherche à créer un réseau décentralisé pour résister à une attaque nucléaire.

Un système complexe de router utilisant les protocoles IP et TCP pour envoyer les paquets.

Des protocoles apparaissent au fil des ans : UDP, DNS, HTTP, HTTPS, TLS, SSL, VOIP...

Qu'est-ce qu'internet ?

Une construction à partir du « bas »

  • Réseau local - Laboratoire, Département
  • Réseau local - Campus, Entreprise
  • Réseau régional
  • Réseau national
  • Réseau mondial

 

3 niveaux d’interconnexion

  • Postes de travail (ordinateur, terminal...)
  • Liaisons physiques (câble, fibre, RTC...)
  • Routeurs

Qu'est-ce qu'internet ?

Une somme d'invention qui s'accumule

- Mécanismes réseau de base (TCP/IP)

- Gestion des noms et des adresses

- Des outils et des protocoles spécialisés

- Le langage HTML et CSS

- La technologie Adobe Flash

- Le langage Javascript puis Typescript

- De nombreux frameworks...

- Les Websockets

- QUIC - HTTP/3

- Etc...

Les requêtes - Qu'est-ce que le modèle OSI ?

Le modèle OSI (Open Systems Interconnection) développé par l'ISO (Organisation internationale de normalisation) est un cadre conceptuel standard qui décrit comment les différentes couches d'un système de communication réseau interagissent.

Le modèle possède 7 couches qui permettent :

  • Standardiser les communications réseau entre différents systèmes et technologies.
  • Clarifier les responsabilités de chaque couche pour faciliter le dépannage et le développement.
  • Encourager l’interopérabilité entre les fabricants et les développeurs.

Les couches : Physique, Liaison de données et Réseau

Physique - Gère les aspects matériels de la transmission des données (câbles, signaux, connecteurs, etc.).

Exemples : Ethernet, USB, Wi-Fi.

Liaison de Données - Assure le transfert fiable des données entre deux nœuds adjacents et gère les adresses matérielles (MAC) et la détection/correction d’erreurs.

Exemples : Ethernet, PPP (Point-to-Point Protocol).

Réseau - Responsable de l'acheminement des paquets à travers plusieurs réseaux et gère les adresses IP et le routage.

Exemple : IP (Internet Protocol).

Les couches : Transport, Session et Présentation

Transport - Garantit le transfert fiable et ordonné des données entre deux hôtes et gère la segmentation, le contrôle de flux et la correction d'erreurs.

Exemples : TCP, UDP.

Session - Gère les sessions de communication entre deux applications et s'occupe de l’établissement, du maintien et de la terminaison des connexions.

Exemple : NetBIOS.

Présentation - Assure la traduction, le chiffrement/déchiffrement et la compression des données et fait en sorte que les données soient lisibles par l'application.

Exemple : SSL/TLS, JPEG, ASCII.

La couche Application

Fournit des services réseau aux applications utilisateur et inclut les protocoles utilisés pour le courrier électronique, le web, etc.

La communication se fait de la plus basse à la plus haute, donc de la couche Physique jusqu'à la couche Application.

 

HTTP - HyperText Transport Protocol - Port 80

RPC - Remote Procedure Call - Port 1024-5000

SSH - Secure Shell - Port 22

FTP - File Transfer Protocol - Port 21

SMTP - Simple Mail Transfer Protocol - Port 25

 

Utilisent les sockets - interface de programmation permettant l'échange de données (via TCP ou UDP).

Comment fonctionne une requête ?

Comment fonctionne une requête ?

Qu'est-ce que l'UDP ?

Le plus simple, service de type best-effort : les paquets peuvent être perdus ou arriver dans le désordre.

Rapide : pas de délai de connexion, pas d'état entre émetteur / récepteur.

Léger : petite en-tête donc économie de bande passante, sans contrôle de congestion.

Qui utilise l'UDP ?

Streaming audio ou video, mieux vaut perdre quelques frames que ralentir tout le flux.

Jeu video pour le temps réel des jeux en ligne comme League of Legends ou Call of Duty.

WebRTC pour le temps réel dans le Web pour des chats textuels ou video.

Autres utilisations d'UDP

 

Applications qui envoient peu de données et qui ne nécessitent pas un service fiable : DNS, SNMP, BOOTP/DHCP.

Qu'est-ce que TCP ?

Transport fiable en mode connecté : assure la délivrance des données en séquence entre deux adresses.

Contrôle la validité des données reçues, organise les reprises sur erreur ou sur temporisation.

Réalise le contrôle de flux : ecriture dans un tampon, et le contrôle de congestion.

Qui utilise TCP ?

HTTP car chaque donnée est essentielle, évitons de n'envoyer qu'une partie du mot de passe de l'user.

FTP car stocker un fichier à moitié ou avec une écriture dans le mauvais ordre ne sert à rien.

SMTP car on ne peut pas perdre la demande d'envoi d'un e-mail.

UDP vs TCP en résumé

UDP - User Datagram Protocol

Rapide, léger, sans connexion.

Pas de garantie de livraison, d’ordre, ou de retransmission.

Idéal pour : streaming, VoIP, jeux en ligne (faible latence).

 

TCP - Transmission Control Protocol

Fiable, orienté connexion.

Garantit la livraison, l’ordre, et la retransmission des données perdues.

Idéal pour : navigation web, email, transferts de fichiers (intégrité critique).

 

En bref : UDP pour la vitesse, TCP pour la fiabilité.

Qu'est-ce qu'une Architecture N-Tiers ?

Une architecture N-tiers est un modèle de conception de logiciels dans lequel une application est divisée en plusieurs couches (ou tiers) distinctes, chacune ayant un rôle spécifique. Cette séparation améliore la modularité, la maintenabilité, et la scalabilité de l’application.

 

Chaque tier est indépendant des autres et interagit avec eux via des interfaces définies.

Les tiers peuvent être déployés sur des serveurs distincts ou combinés sur un même serveur, selon les besoins.

Dans quel cas a-t-on besoin d'une architecture N-Tiers ?

  • Modularité : Chaque tier peut être développé, testé et déployé séparément.
  • Facilité de maintenance : Les modifications dans un tier n’affectent pas directement les autres.
  • Scalabilité : On peut faire évoluer chaque tier indépendamment (par exemple, augmenter les ressources pour le back-end sans toucher au front-end).
  • Réutilisabilité : Un tier, comme une API, peut être utilisé par plusieurs applications.
  • Sécurité renforcée : Les données sensibles peuvent être isolées dans le tier adéquat (exemple : la base de données).

Dans quel cas a-t-on besoin d'une architecture N-Tiers ?

Exemple concret : e-commerce

Tier présentation : Une boutique en ligne où les utilisateurs naviguent (front-end).

Tier logique applicative : Traitement des commandes, gestion du panier, calcul des frais de livraison.

Tier données : Base de données contenant les informations sur les utilisateurs, produits, et commandes.

Qu'est-ce qu'une architecture Client / Serveur ?

Vous est-il déjà arrivé d’entrer dans un restaurant et de commander votre repas directement au cuisinier ?

Vous attendez qu’un serveur vienne prendre votre commande. Vous lui dites ce que vous voulez manger et celui-ci va dans la cuisine et le dit au cuisinier.

Vous n'utilisez pas nécessairement le bon jargon pour le cuisinier, et ce dernier ne sait peut-être pas à quelle table envoyer votre plat lorsqu'il est prêt.

 

Ici notre Client est le serveur et notre Serveur le cuisinier.

Le but est de permettre à notre utilisateur d'utiliser le Serveur facilement en utilisant notre Client.

Quels sont les autres types ?

Monolithe : unifiée et contient toutes les fonctionnalités  dans un seul bloc. (Ruby on Rails)

Microservice : divisée en plusieurs services indépendants, chacun ayant une fonction spécifique.

Événementielle : les composants communiquent en émettant ou en réagissant à des événements via un message broker.

Quels sont les autres types ?

Serverless : le code est exécuté dans des environnements où l'infrastructure est entièrement gérée par un fournisseur.

Hexagonale : centrée sur la logique métier, elle définit des interfaces pour interagir avec l'extérieur via des adaptateurs.

Et d'autres...

Quels sont les autres types ?

Type Modularité Scalabilité Complexité
N-tiers Moyenne Bonne Moyenne
Monolithique Faible Limitée Faible
Microservices Élevée Très bonne Élevée++
Événementielle Élevée Très bonne Élevée
Serverless Moyenne Automatique Élevée
Hexagone Très élevée Bonne Moyenne++

Pourquoi réaliser une architecture Client / Serveur ?

Centralisation des ressources et des données

Simplifie la gestion et la maintenance, facilite les sauvegardes et la sécurité des données et évite la duplication inutile des données.

Séparation des responsabilités

Le client se concentre sur l'interface utilisateur (UI) et l'expérience utilisateur. Le serveur gère les calculs, la logique métier et la gestion des données. Cela permet une spécialisation.

Évolutivité

Les serveurs peuvent être mis à niveau pour gérer un nombre croissant de clients, les clients peuvent également être développés ou diversifiés (ordinateurs, mobiles, tablettes) sans affecter le serveur.

Le Middleware - 1

Un middleware est un logiciel intermédiaire qui agit comme un pont entre différentes applications, systèmes ou composants au sein d’une architecture informatique.

  1. Communication : Permet aux applications de systèmes distincts de communiquer, même si elles utilisent des technologies ou des protocoles différents.
  2. Abstraction : Cache la complexité technique des interactions en fournissant une interface simplifiée pour les développeurs.
  3. Gestion des données : Transfère, transforme ou synchronise les données entre applications.
  4. Sécurité : Peut inclure des services d’authentification, d’autorisation et de chiffrement pour les échanges.
  5. Scalabilité et performances : Optimise les échanges et gère les volumes élevés de données ou de connexions.

Le Middleware - 2

Exemples

  • Une application web utilise un middleware pour transformer une requête HTTP en une commande pour une base de données.
  • Une plateforme e-commerce intègre un ERP via un middleware pour synchroniser les stocks.
  • Un système IoT utilise un middleware orienté message (comme Kafka) pour collecter et distribuer les données des capteurs.

Bonnes pratiques de développement d'application

Il existe énormément de bonnes pratiques et méthodologies pour réaliser une bonne conception d'application.

Nous allons voir ensemble le Domain Driven Design qui possèdent de nombreux avantages et permet de gérer proprement les N-tiers.

Qu'est-ce que le Domain Driven Design ?

Première fois cité dans le livre de Eric Evans du même titre publié en 2003

Le DDD est une architecture pour la conception de logiciels

Place la logique métier au centre des préoccupations.

Pourquoi utiliser le Domain Driven Design ?

Isoler la logique métier de la logique applicative / infrastructure.

Abstraire les outils et technologies utilisés.

Un seul et même langage pour toute l'équipe, il est très facile de collaborer.

Identifier les domaines d'activités de l'entreprise

Domain Driven Design - 1

Domain Driven Design - 2

La couche domaine met en œuvre la logique commerciale centrale, indépendante des cas d'utilisation, du domaine/système.
La couche application met en œuvre les cas d'utilisation de l'application basés sur le domaine. Un cas d'utilisation peut être considéré comme une interaction de l'utilisateur avec l'interface utilisateur (UI).
La couche présentation contient les éléments de l'interface utilisateur (pages, composants) de l'application.
La couche infrastructure soutient les autres couches en mettant en œuvre les abstractions et les intégrations avec les bibliothèques et les systèmes tiers.

Architecture Hexagonale

Des questions ?

TP - Découverte des sockets

Création de socket en NodeJS

Nous allons créer une première application en Client / Serveur en NodeJS pour réaliser notre premier "Hello world". N'hésitez pas à télécharger NodeJS pour la suite du TP si vous ne l'avez pas encore.

Pour faciliter le rendu final des TPs et exercices, nous allons tout de suite créer un dépôt sur Github en publique et le cloner sur notre machine.

Ensuite, créez le dossier "TP-Sockets" et lancez la commande :

npm init

Acceptez toutes les options par défaut, nous utiliserons la librairie Net pour utiliser les sockets et faire communiquer notre client et notre serveur.

Création de socket en NodeJS

Créons un fichier server.js qui contiendra toute la logique permettant de renvoyer "Hello world".

Ensuite, ajoutons le code suivant :

const net = require("net");

// Port de la socket pour le serveur
const PORT = 5001;

// Création du serveur, la socket ouverte par le client est en paramètre.
const server = net.createServer((socket) => {
  console.log("--- Client connecté.");
  // Écouter les requêtes RPC du client
  socket.on("data", (data) => {
    const name = data.toString();

    socket.write(`Hello world ${name}!`);
  });
  socket.on("end", () => {
    console.log("--- Client déconnecté.");
  });
});

// Démarre le serveur sur le port 5001
server.listen(PORT, () => {
  console.log(`Serveur RPC en écoute sur le port ${PORT}`);
});

Création de socket en NodeJS

Créons un fichier client.js qui contiendra toute la logique permettant de recevoir "Hello world".

Ensuite, ajoutons le code suivant :

const net = require("net");

const PORT = 5001;

// Connexion au serveur
const client = net.createConnection(PORT, "localhost", () => {
  console.log("--- Connecté au serveur.");

  // Requête pour appeler le serveur avec votre nom.
  client.write("Me");
});

// Réception des réponses du serveur RPC
client.on("data", (data) => {
  const response = data.toString();

  console.log(response);
  client.end(); // Terminer la connexion après la réponse
});

client.on("end", () => {
  console.log("--- Déconnecté du serveur.");
});

Création de socket en NodeJS

Maintenant que les fichiers sont prêts, lancez un terminal avec le serveur :

node server.js

Et un terminal avec le client quand le serveur écoute :

node client.js

Que remarquez-vous ?

 

Appelez-moi pour que l'on puisse valider ensemble le TP.

Exercice 1 : Utiliser du JSON

Nous allons utiliser un autre moyen qu'une simple string pour communiquer avec le serveur. Ajoutez la logique nécessaire pour que le serveur puisse maintenant réagir à un type de requête en utilisant du JSON :

{
	"request": "echo",
    "params": {
    	"text": "This is a test."
    }
}

N'hésitez pas à utiliser JSON.parse et JSON.stringify pour générer ou parser les messages envoyés par les sockets.

Le serveur doit donc vérifier le type de request, si c'est égal à "echo", répondre le "text" envoyé dans "params" au client.

 

Appelez-moi pour que l'on puisse valider ensemble.

Exercice 2 : Créer un serveur IRC basique en Node.js

Créez un serveur dans un dossier "MyIRC" capable d'accepter des connexions multiples via TCP, ceci simule un serveur IRC, nous utiliserons donc le port par défaut qui est 6667 pour ce genre de service. Vous devez gérez les cas suivants : quand un utilisateur se connecte pour la première fois, demandez son pseudo et informer les autres utilisateurs qu'il vient de rejoindre le chat et quand il se déconnecte. Lorsqu'un utilisateur envoie un message, le transmettre à tous les autres utilisateurs connectés.

Utilisez telnet comme client :

telnet localhost 6667

(Utilisez brew install telnet pour Macos ou Enable-WindowsOptionalFeature -Online -FeatureName TelnetClient pour Powershell)

Exercice 3 : Ajouter une commande

Ajoutez la commande /list permettant d'afficher la liste de tous les pseudos des clients actuellement connectés au chat.

 

Appelez-moi pour que l'on puisse valider ensemble.

Exercice 4 : Ajouter le chuchotement

Ajoutez la commande /whisper permettant de n'envoyer un message qu'à un utilisateur en particulier, le message doit s'afficher différement des autres.

Par exemple :

 

 

 

 

Appelez-moi pour que l'on puisse valider ensemble.

/list
# 1. Valentin
# 2. Amélie

/whisper Valentin "Comment ça va ?"
# Affiche chez Valentin :
# [Whisper][Amélie] Comment ça va ?

Exercice 5 - Bonus : Ajouter la gestion des canaux

Ajoutez la logique des canaux de discussions, ajoutez la commande /channels list pour lister les canaux, /channels create pour en créer un, /channels join pour le rejoindre.

Un utilisateur doit être de base dans le canal "global" où tous les utilisateur sont par défaut.

Quand un utilisateur rejoins un canal et envoie un message, seuls ceux dans ce canal sont capables de le voir.

 

Appelez-moi pour que l'on puisse valider ensemble.

Les modes de communications entre processus

2.

Les modes de communications entre processus

Par mémoire partagée

Par messages

Par signaux

Que cela soit en local, entre processus s'exécutant sur le même hôte, ou à distance, entre processus s'exécutant sur des hôtes distants. Sauf pour les signaux, seulement en local.

Mémoire partagée

Les processus se partagent une zone de mémoire commune dans laquelle ils peuvent lire et/ou écrire

Mémoire partagée

L'accès à une mémoire partagée n'est possible que par deux actions : Read et Write.

 

Avantages :

- Communications transparentes.

- Limitation des copies mémoire.

 

Inconvénients :

- Problème si deux écritures simultanées (ordre d’ordonnancement, atomicité des opérations).

- Les processus P1 et P2 doivent se synchroniser pour accéder au tampon partagé (verrou, sémaphore, …).

Mémoire partagée

En local

Les deux processus s'exécutent sur la même machine donc peuvent se partager une partie de leur espace d'adressage.

Exemple : les threads s'exécutent dans le contexte d'un même processus.

 

A distance

La mémoire partagée est physiquement répartie, le gestionnaire de mémoire virtuelle permet de regrouper les différents morceaux selon un seul espace d'adressage.

Attention : problème de cohérence mémoire...

Les tubes de communications

Communications locales de type mémoire partagée.

Le canal de communication est unidirectionnel (pas de problème de synchronisation), communications entre 2 processus uniquement : l'un écrit dans le tube, l'autre lit.

 

Exemple : cat package.json | wc -l

 

Dans cette situation, cat peut seulement écrire et wc peut seulement lire.

Les tubes de communications

Par messages

Les processus n'ont pas accès à des "variables" communes et ne communiquent qu'en s'envoyant des messages.

Ils utilisent deux primitives : send() et recv().

Des zones de mémoire locales à chaque processus permettent l'envoi et la réception des messages et l'émetteur/récepteur doit pouvoir désigner le récepteur/émetteur distant. (adresse)

 

Ces opérations peuvent être bloquantes ou non-bloquantes.

Opération bloquante et non-bloquante

Une opération bloquante bloque le processus jusqu'à ce qu'elle se termine.

Cela permet de simplifier les communications entre processus et éviter de l'asynchrone.

 

Une opération non-bloquante permet au processus de continuer son execution en attendant que des données soient émises ou reçues.

Attente active - appels réguliers à la primitive jusqu'à complétion.

Attente passive - le système informe le processus par un moyen quelconque de la complétion de l'opération (signaux par exemple)

Par signaux

Mécanisme de communications locales interprocessus (ou depuis le noyau vers un processus) permettant de notifier un événement.

Le déclenchement d'un signal interromps le logicielle quand l'événement se produit.

Pour utiliser les signaux, le processus doit :

- Indiquer les signaux qu'il souhaite capter (provoquant son interruption)

- Mettre en place un handler (fonction particulière) qui sera exécuté quand l'événement se produira.

 

Exemple : CTRL+C dans un terminal envoie le signal SIGINT qui permet au terminal d'arrêter la commande en cours.

Par messages - les sockets

Deux processus communiquent en émettant et recevant des données via les sockets, pour faire du passage de messages, il est nécessaire de désigner l'autre extrémité de la communication.

 

Deux types de désignations :

Explicite - Designation du ou des processus destinataire(s)/émetteurs.

Implicite - recevoir un message de n'importe qui, émettre un message à n'importe qui (diffusion) ou une phase d'établissement de connexion désigne les deux entités communicantes.

Qu'est-ce qu'une socket ?

Une socket est une connexion entre deux processus et est représenté par un fichier virtuel avec les opérations d'ouverture, fermeture, écriture, lecture, …

En bas niveau, on peut donc les utiliser comme un descripteur de fichier.

Elles sont des portes d'entrées / sorties vers le réseau (la couche transport).

 

Il y a trois types de sockets :

Stream socket - TCP

Datagram socket - UDP

Raw socket - IP

Les sockets - adressage

Une socket est identifiée par une adresse de transport qui permet d'identifier les processus de l'application concernée.

Format de l'adresse :

<Adresse IP>:<Numéro de port>

La première identifie l'hôte dans le réseau, l'autre l'application lancée au sein de l'hôte.


Pour les ports, on évite d'utiliser ceux en dessous de 1024 qui sont souvent réservés par les "well-knowns ports".

Les sockets - connexion

Les sockets - connexion

Règles pour la connexion

  1. Pour que le client puisse contacter le serveur, le processus serveur doit déjà tourner et le serveur doit avoir créé au préalable une socket pour recevoir les demandes de connexion des clients.
  2. Le client contacte le serveur en créant une socket locale au client et en spécifiant une adresse IP et un numéro de port pour joindre le processus serveur
  3. Le client demande alors l'établissement d'une connexion avec le serveur
  4. Si le serveur accepte la demande de connexion, il crée une nouvelle socket permettant le dialogue avec ce client, cela permet au serveur de dialoguer avec plusieurs clients.

Les serveurs multi-protocoles

Un serveur qui offre le même service en mode connecté et non connecté.

Exemple : DAYTIME port 13 sur UDP et sur TCP qui permet de lire la date et l'heure sur le serveu

  • 13/TCP : la demande de connexion du client déclenche la réponse (à une requête donc implicite) : le client n’émet aucune requête.
  • 13/UDP : la version UDP de DAYTIME requiert une requête du client : cette requête consiste en un datagramme arbitraire qui n‘est pas lu par le serveur mais qui déclenche l’émission de la donnée côté serveur.

Le serveur écoute sur 2 sockets distinctes pour rendre le même service.

Pourquoi un serveur multi-protocoles ?

Certains systèmes ferment tout accès à UDP pour des raisons de sécurité (pare-feu).

Non duplication des ressources associées au service (corps du serveur).

Les serveurs multi-services

Un serveur qui répond à plusieurs services (une socket par service).

Pourquoi un serveur multi-services ?

Problème lié à la multiplication des serveurs : le nombre de processus nécessaires et les ressources consommées qui y sont associées.

Avantages

  • Le code réalisant les services n’est présent que lorsqu’il est nécessaire.
  • La maintenance se fait sur la base du service et non du serveur, l’administrateur peut facilement activer ou désactiver un service.

Fonctionnement d'un serveur multi-services

  1. Le serveur ouvre une socket par service offert, attend une connexion entrante sur l’ensemble des sockets ouvertes.
  2. Lorsqu’une demande de connexion arrive, le serveur crée un processus fils qui prend en compte la connexion.
  3. Le processus fils exécute (via exec() sur système UNIX) un programme dédié réalisant le service demandé.

Les processus démons

L'invocation d'un service Internet standard (FTP, TELNET, RLOGIN, SSH, …) nécessite la présence côté serveur d'un processus serveur qui tourne en permanence et qui est en attente des requêtes clientes.

A priori, il faudrait un démon par service.

Problème : multiplication des services == multiplication du nombre de démons. Sous UNIX, un super-démon : inetd.

# /etc/inetd.conf

# Internet services syntax :
# <service_name> <socket_type> <proto> <flags> <user> <server_pathname> <args>
# wait : pour un service donné, un seul serveur peut exister à un instant donné
# donc le serveur traite l'ensemble des requêtes à ce service
# stream --> nowait : un serveur par connexion

ftp stream tcp nowait root /etc/ftpd ftpd -l
tftp dgram udp wait root /etc/tftpd tftpd
shell stream tcp nowait root /etc/rshd rshd

Les appels de procédures distantes - RPC

Analogie avec un appel de fonction

La fonction ou procédure ne rend la main au programme appelant qu'une fois le traitement (calcul) terminé.

RPC - Remote Procedure Call

Permettre à un processus de faire exécuter une fonction par un autre processus se trouvant sur une machine distante, cela se traduit par l'envoi d'un message contenant l'identification de la fonction et les paramètres, une fois le traitement terminé, un message retourne le résultat de la fonction à l'appelant.

Les appels de procédures distantes - RPC

Les avantages du RPC

Rapide et utilise des ressources distantes côté client comme l'appel d'une fonction classique.

L'application n'a pas à manipuler directement les sockets ni gérer la communication entre les deux.

L'implémentation des RPC est indépendante de l'OS.

Les limites du RPC

La procédure distante n'a pas accès aux variables du client, aux périphériques d'E/S (affichage d'une erreur !)

Un appel de procédure est synchrone, l'instruction suivante doit attendre que l'appel soit terminé.

Impossible de passer des références ou pointeurs via la procédure.

gRPC - la version moderne

Définition de service très simple utilisant Protocol Buffers pour optimiser les communications.

Facilement déployable en env de Dev ou Production avec des millions de RPCs par seconde.

Streaming bidirectionnel et authentification entièrement intégrée avec le transport basé sur HTTP/2

Protocol Buffers

Mécanisme extensible de Google, indépendant du langage / la plateforme, pour la sérialisation des données.

Pensez à XML, mais en plus petit, plus rapide et plus simple. Ultra performant car la donnée est sérialisée.

Génère automatiquement une librairie pour envoyer et recevoir vos données.

Protocol Buffers - Déclarations

syntax = "proto3";

package todo;

// Définition du service
service TodoService {
  rpc AddTask (Task) returns (AddTaskResponse);
  rpc GetTasks (Empty) returns (TaskList);
}

// Messages utilisés par le service
message Task {
  string id = 1;
  string description = 2;
}

message AddTaskResponse {
  string message = 1;
}

message TaskList {
  repeated Task tasks = 1;
}

message Empty {}

TP - Découverte des signaux

Gestion des signaux en NodeJS

Créez le dossier "TP-Signaux" et ajoutez le fichier "index.js" à l'intérieur. Ce fichier va contenir la logique pour détecter un signal.

// Fonction générique pour gérer les signaux
async function handleSignal(signal) {
  console.log(`Signal ${signal} reçu.`);
}

// Ecoute du signal SIGINT.
process.on("SIGINT", () => handleSignal("SIGINT"));

// Simulation d'une application qui reste active
console.log("Application en cours d'exécution.");
console.log(
  "Appuyez sur CTRL+C pour envoyer un signal."
);

// Execute la fonction toutes les 5 secondes.
setInterval(() => {
  console.log("Le processus est toujours actif...");
}, 5000);

Lancez le script et essayez maintenant de réaliser un CTRL+C. Appelez-moi pour que l'on puisse valider ensemble.

Exercice Signaux 1 - Quitter proprement

Nous voulons que notre solution puisses nettoyer avant de s'arrêter après un CTRL+C, il faut donc écrire dans le terminal "Nettoyage en cours..." et arrêtez le processus au bout de 5 secondes.

Ajoutez la logique grâce à setTimeout et process.exit(0) pour arrêter le processus correctement au bout d'un certains temps.

 

Appelez-moi pour que l'on puisse valider ensemble.

Exercice Signaux 2 Bonus - Ajouter le signal SIGTERM

Nous voulons gérer aussi le signal SIGTERM qui est lancé par la commande kill -15 <PID> sur Linux, ce signal est envoyé quand un processus est tué par le système.

Ajoutez le même comportement pour SIGTERM.

 

Appelez-moi pour que l'on puisse valider ensemble.

 

ATTENTION cet exercice ne fonctionne pas sur Windows, vous pouvez passer à la suite.

Exercice Signaux 3 - Bloquer un signal

Par soucis de sécurité, nous voulons que notre solution ne puisses pas être arrêter dans des phases importantes de son fonctionnement.

Réaliser un interval où toutes les 5 secondes, la solution passe d'un état où elle peut être arrêté via un signal à un état où il n'est pas possible de l'arrêter.

Ecrivez dans le terminal que l'arrêt est impossible pour le moment quand l'utilisateur tente de l'arrêter.

 

Appelez-moi pour que l'on puisse valider ensemble.

Exercice Signaux 4 - Cas concret

Dupliquer le dossier "MyIRC" et nommez-le "MyIRC-Signal".

Ajoutez la logique de gestion des signaux à votre MyIRC, quand l'utilisateur tente de stopper le serveur via un signal, envoyez à tous les clients connectés que le serveur va fermer dans 5 secondes et arrêter le serveur au bout des 5 secondes.

 

Appelez-moi pour que l'on puisse valider ensemble.

TP - Découverte de gRPC

Réalisez une architecture RPC en NodeJS

Nous allons créer un service gRPC avec Node.js permettant de gérer une liste de tâches (to-do list).

Créez le dossier "TP-RPC" et initialisez le projet nodejs :


Nous allons maintenant ajouter la logique de Protocol Buffers.

npm init -y
npm install @grpc/grpc-js @grpc/proto-loader

Réalisez une architecture RPC en NodeJS

Définissez le fichier Protocol Buffers et nommez-le "todo.proto" :

syntax = "proto3";

package todo;

// Définition du service
service TodoService {
  rpc AddTask (Task) returns (AddTaskResponse);
  rpc GetTasks (Empty) returns (TaskList);
}

// Messages utilisés par le service
message Task {
  string id = 1;
  string description = 2;
}

message AddTaskResponse {
  string message = 1;
}

message TaskList {
  repeated Task tasks = 1;
}

message Empty {}

Réalisez une architecture RPC en NodeJS

Créez le fichier "server.js" suivant :

const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const PROTO_PATH = './todo.proto';

// Chargement du fichier .proto
const packageDefinition = protoLoader.loadSync(PROTO_PATH);
const todoProto = grpc.loadPackageDefinition(packageDefinition).todo;

// Liste des tâches en mémoire
const tasks = [];

// Implémentation des méthodes du service
const addTask = (call, callback) => {
  const task = call.request;
  tasks.push(task);
  callback(null, { message: 'Task added successfully!' });
};

const getTasks = (call, callback) => {
  callback(null, { tasks });
};

// Démarrage du serveur
const server = new grpc.Server();
server.addService(todoProto.TodoService.service, { addTask, getTasks });
server.bindAsync('0.0.0.0:50051', grpc.ServerCredentials.createInsecure(), () => {
  console.log('Server running on http://0.0.0.0:50051');
  server.start();
});

Réalisez une architecture RPC en NodeJS

Créez le fichier "client.js" suivant :

const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');
const PROTO_PATH = './todo.proto';

// Chargement du fichier .proto
const packageDefinition = protoLoader.loadSync(PROTO_PATH);
const todoProto = grpc.loadPackageDefinition(packageDefinition).todo;

// Création du client
const client = new todoProto.TodoService('localhost:50051', grpc.credentials.createInsecure());

// Ajouter une tâche
client.AddTask({ id: '1', description: 'Learn gRPC' }, (err, response) => {
  if (err) console.error(err);
  else console.log(response.message);

  // Récupérer les tâches
  client.GetTasks({}, (err, response) => {
    if (err) console.error(err);
    else console.log('Tasks:', response.tasks);
  });
});

Réalisez une architecture RPC en NodeJS

Lancez votre serveur puis lancez votre client.

Que remarquez-vous ?

 

Appelez-moi pour que l'on puisse valider ensemble.

Exercice 1 : Appel d’une API tierce

Intégrez une API tierce dans votre serveur gRPC.

Méthode :

  • Fournissez un service où le client peut demander la liste des jeux disponible sur une boutique en ligne de jeu.
  • Le serveur gRPC fait un appel à l’API FreeToGame et retourne la réponse.

Pour cela nous allons utiliser la librairie Axios pour réaliser une requête HTTP auprès de l'API.

Exercice 2 : Accès à une base de données

Connectez votre service gRPC à une base de données MongoDB.

Cas d’usage :

Stockez et récupérez des informations sur une liste de produits.

Créez des méthodes pour ajouter, modifier et supprimer des produits.

Utilisez Docker pour lancer facilement une base de donnée en local :

docker run --name mongodb -p 27017:27017 -d mongo

Utiliser la libraire NodeJS MongoDB pour utiliser la base de donnée.

Appelez-moi pour que l'on puisse valider ensemble.

Exercice 3 : Intégration du TLS

Créer un service gRPC qui utilise TLS pour dialoguer en sécurité avec son client. Pour cela, nous allons générer les certificats SSL nous-même à la racine du dossier de l'exercice :

 

 

 

Vous obtiendrez alors les fichiers server.crt et server.key dans le dossier certs. Nous utiliserons alors la méthode createSsl au lieu de createInsecure où serverCert et serverKey sont le contenu des fichiers dans certs.

 

 

Appelez-moi pour que l'on puisse valider ensemble.

mkdir certs
cd certs
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/CN=localhost"
openssl x509 -req -in server.csr -signkey server.key -out server.crt -days 365
grpc.ServerCredentials.createSsl(null, [{
  cert_chain: serverCert,
  private_key: serverKey,
}], true);

Exercice 4 : Gestion des erreurs

Ajoutons dans notre exercice 2 avec la logique de gestion de produit notre gestion d'erreur.

Nous allons donc gérer le cas où nous réalisons un getProduct pour récupérer un produit avec un id mais où l'id n'existe pas.

Renvoyez une erreur INVALID_ARGUMENT au client et intégrez la gestion d'erreur côté client pour afficher un message d'erreur explicite.

 

Appelez-moi pour que l'on puisse valider ensemble.

Exercice 5 Bonus : Stream Video

Créer un service gRPC qui permet à un client de streamer une vidéo en fragments depuis un serveur.

  1. Configuration du projet Node.js avec gRPC.

  2. Définir un fichier .proto décrivant le service de streaming vidéo.

  3. Implémenter un serveur gRPC capable d'envoyer des fragments vidéo en continu.

  4. Créer un client gRPC pour recevoir et stocker dans un fichier les fragments.

Pour cela nous allons utiliser le concept de Stream en NodeJS, inspirez vous du tutoriel de gRPC pour réaliser la logique de stream avec gRPC.

Appelez-moi pour que l'on puisse valider ensemble.

Exercice 6 Bonus : Service de notification

Créer un service gRPC qui permet aux clients d'écouter un stream de notifications pour réagir dès qu'un client crée une nouvelle notification.

Cela ressemble au fonctionnement de notre MyIRC que nous avions réalisé via les Sockets où un client doit pouvoir envoyer un message et le reste des clients vont le recevoir.

N'hésitez pas à vous baser sur ce que vous avez fait lors du Stream de la vidéo.

 

Appelez-moi pour que l'on puisse valider ensemble.

Exercice 7 Bonus : Création d'une interface graphique

Maintenant que notre service de notification est prêt, ajoutons une interface graphique à celui-ci pour découvrir comment utiliser gRPC directement dans une application web.

Pour cela nous allons utiliser la librairie grpc-web pour nous connecter à notre service depuis le frontend pour afficher les notifications.

Suivez la documentation de la librairie pour générer les services.

Choix des technologies libre mais je vous conseille de passer par Vite pour générer le projet de base.

Pour utiliser notre service gRPC, nous allons utiliser Envoy via Docker qui permet de réaliser un Proxy, configuration sur la slide suivante.

Exercice 7 Bonus : Création d'une interface graphique - 2

// envoy.yaml
static_resources:
  listeners:
    - address:
        socket_address: { address: 0.0.0.0, port_value: 8080 }
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              config:
                codec_type: AUTO
                stat_prefix: ingress_http
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: backend
                      domains: ["*"]
                      routes:
                        - match: { prefix: "/" }
                          route:
                            cluster: example_service
                http_filters:
                  - name: envoy.filters.http.grpc_web
                  - name: envoy.filters.http.cors
                  - name: envoy.filters.http.router
  clusters:
    - name: example_service
      connect_timeout: 0.25s
      type: STATIC
      lb_policy: ROUND_ROBIN
      load_assignment:
        cluster_name: example_service
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address: { address: 127.0.0.1, port_value: 50051 }

Appelez-moi pour que l'on puisse valider ensemble.

Connexions à distance

Application permettant à un utilisateur de se connecter (prendre partiellement le contrôle) sur un ordinateur distant (à partir d'un terminal local).

Pour cela, l'utilisateur doit disposer d'un accès autorisé à la machine. On peut executer alors des commandes saisies localement au clavier sur une machine distante.

Par exemple, je peux me connecter depuis Windows à un serveur sous Linux et executer des commandes Linux.

Les protocoles de connexion à distance

telnet - le standard (existe sur de nombreuses plate-formes).

rlogin - uniquement entre machines unix.

ssh - sécurisé (authentification + cryptage), peut transporter le DISPLAY.

 

Aujourd'hui, on utilise essentiellement SSH pour la connexion à des serveurs distants ou pour la connexion avec son gestionnaire de dépôt Git.

Telnet

Un des premiers standard de l'Internet : RFC 854,855 (1983).

Connexion TCP sur le port 23 côté serveur avec une authentification sur le shell distant (mot de passe en clair).

Quand un caractère est tapé au clavier, il est envoyé au serveur qui renvoie un "écho" du caractère ce qui provoque son affichage dans le terminal local.

Prise en compte de l'hétérogénéité : mécanisme de négociation d'options à la connexion (codage des caractères ASCII sur 7 ou 8 bits ?)

Exemple : telnet d'une machine Windows vers une machine Unix, tous les caractères ASCII n'ont pas la même signification

Telnet - Utilisations

// Par le nom de la machine distante (DNS+port 23)
telnet google.com
// Par l'adresse IP de la machine distante (port 23)
telnet 168.192.0.5
// Accès à un autre service (connexion sur un autre port)
telnet 168.192.0.5 80

// Exemple
telnet google.com 80
Trying 142.250.75.238...
Connected to google.com.
Escape character is '^]'.

$
HTTP/1.0 400 Bad Request
Content-Type: text/html; charset=UTF-8
Referrer-Policy: no-referrer
Content-Length: 1555
Date: Thu, 09 Jan 2025 10:50:38 GMT

<!DOCTYPE html>
<html lang=en>
  <meta charset=utf-8>
  <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
  <title>Error 400 (Bad Request)!!1</title>
  <style>
    *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
  </style>
  <a href=//www.google.com/><span id=logo aria-label=Google></span></a>
  <p><b>400.</b> <ins>That’s an error.</ins>
  <p>Your client has issued a malformed or illegal request.  <ins>That’s all we know.</ins>
Connection closed by foreign host.

Telnet - Utilisations - 2

telnet

telnet> ?
Commands may be abbreviated.  Commands are:

close           close current connection
logout          forcibly logout remote user and close the connection
display         display operating parameters
mode            try to enter line or character mode ('mode ?' for more)
telnet          connect to a site
open            connect to a site
quit            exit telnet
send            transmit special characters ('send ?' for more)
set             set operating parameters ('set ?' for more)
unset           unset operating parameters ('unset ?' for more)
status          print status information
toggle          toggle operating parameters ('toggle ?' for more)
slc             change state of special charaters ('slc ?' for more)
auth            turn on (off) authentication ('auth ?' for more)
z               suspend telnet
!               invoke a subshell
environ         change environment variables ('environ ?' for more)
?               print help information
telnet>

Telnet - Network Virtual Terminal

Un terminal "virtuel réseau" qui permet de supporter des environnements hétérogènes réalise la conversion des caractères spéciaux ou des séquences particulières en un format NVT.

Le format NVT

Tous les caractères sont codés sur 8 bits, les 128 caractères ASCII sont transmis tels quels.

NVT redéfinit la signification de certains caractères de commande ASCII : CR (13d) = retour au début de la ligne, LF (10d) = déplacement d'une ligne vers le bas.

Dans le format NVT, RETURN ou ENTER se traduit par CR-LF

Qu'est-ce que SSH ?

SSH pour Secure SHell est un protocol permettant l'ouverture d'un shell à distance de manière sécurisée.

 

Points forts

  • Les communications sont cryptées : une authentification à base de clés.
  • Permet de transporter des fenêtres graphiques via le tunnel SSH (multiplexage de plusieurs flux dans la connexion).

 

Pour la connexion, sur le port 22 en TCP côté serveur.

Exemple : Vous pouvez lier une clé SSH à votre compte Github pour pouvoir gérer beaucoup plus facilement les accès à votre dépôt.

La sécurité avec SSH

La qualité de la sécurité dépend :

  • du secret de la clé
  • de la longueur de la clé (plus il y a de bits, plus il est difficile d'essayer toutes les clés en Brut Force)
  • de la difficulté d'inversion de l'algorithme de chiffrement

Deux types d'algorithmes

Symétrique - même clé privée secrète partagée utilisée pour le chiffrement et le déchiffrement, l'émetteur et le récepteur doivent se mettre d'accord sur la clé à utiliser.

Exemple : AES, DES

Asymétrique - utilisation d'une clé publique pour le chiffrement et d'une clé privée. Pour qu'un émetteur envoie un message chiffré, il suffit qu'il connaisse la clé publique du destinataire

Comment être sûr que la clé publique est bien celle du destinataire escompté ? On utilise alors des certificats : association d'une clé publique et d'un nom de destinataire signée par un tiers de confiance.

Exemple : RSA, SSL, TLS

Qu'utilise SSH ?

Algorithme asymétrique pour l'authentification : généralement RSA basé sur l'arithmétique modulo.

Algorithme symétrique pour les communications : utilisation de RSA pour échanger la clé de l'algorithme symétrique pour un chiffrement et déchiffrement moins coûteux.

Comment SSH gère l'authentification ?

  1. Automatique forte "améliorée" avec fichiers rhosts ou hosts.equiv mais combinée avec une authentification par RSA, vérification de la clé provenant du client et mot de passe demandé lors de la première connexion puis ajout du couple (@IP, clé publique) du serveur dans le fichier du client. (/etc/ssh/ssh_known_hosts ou ~/.ssh/ssh_known_hosts)
  2. Automatique forte par RSA (asymétrique) - le client génère un couple de clés et copie la clé publique dans le fichier ~/.ssh/authorized_keys sur le serveur. le client envoie au serveur sa clé publique ; si elle est dans le fichier, le serveur génère un nb aléatoire de 256 bits qu'il chiffre avec la clé envoyée par le client ; le client déchiffre avec sa clé privée puis la renvoie avec hachage MD5.

Comment SSH fonctionne ?

Comment utiliser SSH ?

# Se connecter à un serveur
ssh -l user hostname
ssh user@hostname

# Éxecute une commande directement à distance
ssh -l user hostname cmd
ssh user@hostname cmd

# Copie de fichiers à distance
scp file1 file2 user@hostname:

# Copie un dossier
scp -r dir user@hostname:/tmp

TP - Découverte de SSH

Interagir avec un serveur via SSH - 1

Nous allons créer un serveur utilisant SSH grâce à Docker.

Pour cela, nous utiliserons l'image linuxserver/openssh-server.

Nous allons d'abord créer votre paire de clé via l'image :

docker run --rm -it --entrypoint /keygen.sh linuxserver/openssh-server

Choississez RSA et 4096 comme options.

Vous allez voir deux clés dans le terminal, une privée et une publique. Nous allons les stocker dans le dossier dédié et nous allons créer un sous-dossier "test" soit dans "~/.ssh/test/" avec pour nom "id_rsa" et "id_rsa.pub" pour la privée et la publique.

Sur Windows, vos clés seront dans le dossier C:\Users\TonNom\.ssh\test\

Interagir avec un serveur via SSH - 2

Maintenant que nous avons généré notre paire de clé, nous allons lancer le serveur en lui donnant accès à notre clé publique.

Lancez la commande suivante :

docker run -d --name openssh-server -e USER_NAME=user -e PUBLIC_KEY="$(cat ~/.ssh/test/id_rsa.pub)" -p 2222:2222 linuxserver/openssh-server

 

Attention, ici nous utiliserons le port 2222 pour le port SSH.

Le serveur est maintenant prêt pour la suite du TP.

Interagir avec un serveur via SSH - 3

Avant de nous connecter, nous devons ajouter les bonnes permissions à notre clé privée, lancez-la commande :

chmod 600 ~/.ssh/test/id_rsa

Ou pour Windows :

icacls C:\Users\VotreUtilisateur\.ssh\test\id_rsa /inheritance:r /grant VotreUtilisateur:F

Maintenant que le serveur est lancé, nous allons nous connecter :

ssh -i ~/.ssh/test/id_rsa user@localhost -p 2222

 

Vérifiez que vous êtes bien sur le serveur en réalisant des commandes de bases.

Appelez-moi pour que l'on puisse valider ensemble.

Exercice 1 - Envoi de fichier et commandes

Comme vu ensemble durant le cours, il est possible d'exécuter une commande ou même d'envoyer un fichier sur le serveur.

  1. Réalisez la commande pour exécuter directement ls côté serveur.
  2. Réalisez la commande pour envoyer un fichier directement côté serveur. (Attention, il faut utiliser le flag -P pour définir le port)

 

Appelez-moi pour que l'on puisse valider ensemble.

Transfert de fichiers et autres (FTP, TFTP, NFS, SMB)

Copie intégrale d'un fichier d'un système de fichiers vers un autre en environnement hétérogène.

L'hétérogénéité concernant les fichiers est dépendante d'un système à l'autre :

  • Représenter les noms de fichier (longueur, caractère espace,…)
  • Droits d'accès au fichier (lecture, écriture, exécution, propriétaire, …)
  • Représentation des données contenues dans le fichier (saut de ligne…), par exemple : mode ascii - transfert au format NVT avec conversion au format local ou mode binary - transfert sans conversion.

Les types de protocoles

Plusieurs protocoles

  • Copie de fichiers à distance : rcp, scp
  • Protocole de transfert de fichiers avec accès aux systèmes de fichiers local et distant : ftp, tftp, sftp

 

Type client/serveur

le client interagit avec l'utilisateur, le système de fichiers local et les protocoles réseau.

le serveur interagit avec les protocoles réseau et le système de fichiers du serveur.

Ne pas confondre avec les protocoles d'accès aux fichiers distants comme NFS (RPC), SMB (Microsoft)

FTP, TFTP et SFTP

Standard TCP/IP pour le transfert de fichiers : connexion TCP sur le port 21 côté serveur.

Contrôle d'accès au serveur distant en utilisant un login et un mot de passe, attention le mot de passe circule en clair.

Particularité de FTP par rapport à TELNET, etc :

  • Utilisation de 2 connexions TCP
    • Contrôle - échange des commandes et des réponses entre le client et le serveur - “contrôle hors-bande".
    • Données - transfert des fichiers de données vers/depuis l'hôte distant (sur le port TCP/20 côté serveur).
  • Le serveur FTP maintient un "état" : répertoires courants local et distant, username.

Scénario d'une connexion - 1

Scénario d'une connexion - 2

  1. Le client FTP se connecte sur le port 21 du serveur - le port 21 sert à envoyer des commandes au serveur FTP (put, get, cd, …).
  2. si une commande nécessite que des données soient reçues ou transmises (ls, get, put, …), le client envoie une commande PORT au serveur indiquant un port sur lequel le serveur va créer une connexion ftp-data depuis son port 20.
  3. La connexion ftp-data est close dès que le transfert est terminé.

Requêtes FTP - 1

RETR <filename>

Déclenche la transmission par le serveur du fichier <filename> sur le canal de données.

STOR <filename>

Déclenche la réception d'un fichier qui sera enregistré sur le disque sous le nom <filename>. Si un fichier existe déjà, il sera remplacé.

APPE <filename>

Déclenche la réception d'un fichier qui sera enregistré sur le disque sous le nom <filename>. Si un fichier existe déjà, les données seront ajoutées au fichier.

ABOR - Abandon d'un transfert en cours.

PWD - Impression du répertoire actuel.

Requêtes FTP - 2

LIST - Liste tous les fichiers et dossiers du répertoire courant.

NLIST - Même que LIST en version courte.

CWD <name> - Change de dossier.

MKD <name> - Création d'un nouveau dossier.

RMD <name> - Suppression d'un dossier.

DELE <filename> - Suppression d'un fichier.

RNFR / RNTO - Renomme un fichier.

STAT - Status courant de la session FTP.

HELP - Affiche l'aide sur les opérations possibles.

Réponses FTP

Status Signification
1xx Réponse positive préliminaire (une autre réponse suivra)
2xx Réponse positive finale (une autre requête est possible)
3xx Réponse positive intermédiaire (une autre requête doit suivre)
4xx Réponse négative temporaire (la même requête peut réussir plus tard)
5xx Réponse négative définitive (la requête n’est pas acceptée)

TFTP et SFTP

TFTP (Trivial File Transfer Protocol) : Version simplifiée de FTP, sans authentification ni cryptage. Il fonctionne sur un seul port (69) et est souvent utilisé pour des transferts simples sur des réseaux locaux.

SFTP (SSH File Transfer Protocol) : Variante sécurisée de FTP qui fonctionne sur SSH (port 22). Il chiffre les données et les identifiants, assurant ainsi la confidentialité et l'intégrité des transferts.

Accès aux fichiers distants

Différences avec le transfert de fichiers

  • L'accès aux fichiers distants est complètement transparent pour l'utilisateur
  • Tout se passe comme si le système de fichiers distant était local
  • L'utilisateur peut éditer le fichier, le modifier, … ; les modifications seront répercutées sur le système de fichiers distant.

NFS et SMB

  • NFS (Network File System) : Protocole de partage de fichiers principalement utilisé dans les environnements Unix/Linux. Il permet de monter des systèmes de fichiers distants et d'accéder aux fichiers comme s'ils étaient locaux, avec une gestion fine des permissions.

  • SMB (Server Message Block) : Protocole de partage de fichiers principalement utilisé dans les environnements Windows. Il permet l'accès, la gestion et le partage de fichiers et imprimantes entre ordinateurs sur un réseau local.

TP - Découverte de FTP

Interagir avec un serveur via FTP - 1

Nous allons créer un serveur utilisant FTP grâce à Docker.

Pour cela, nous utiliserons l'image delfer/alpine-ftp-server

Nous allons d'abord télécharger un client FTP comme FileZila

Ensuite, lancez la commande Docker :

docker run -d -p 21:21 -p 21000-21010:21000-21010 -e USERS="user|password" -e PASV_ADDRESS=127.0.0.1 delfer/alpine-ftp-server

Cela va lancer le serveur FTP.

Interagir avec un serveur via FTP - 2

Lancez votre client FileZila et ajouter les informations suivantes pour vous connecter en haut du logiciel :

Hôte : localhost

Nom d'utilisateur : user

Mot de passe : password

Et appuyez sur Connexion rapide.

 

Lisez bien les logs juste en dessous et retrouvez les commandes réalisés par votre client FTP avec le serveur FTP.

Testez d'ajouter des fichiers ou des dossiers.

Appelez-moi pour que l'on puisse valider ensemble.

Gestion d’utilisateurs distants avec NIS

NIS - Network Information System

Introduit par SUN en 1985 (Yellow Pages (yp) à l'origine), n'est pas un standard de l'Internet mais est largement utilisé.

C'est une base de données distribuée qui permet le partage d'informations système (/etc/passwd, /etc/hosts, …).

Objectif

  • Réduire le temps d'administration d'un parc de machines
  • Simplifier la gestion des comptes, des mots de passe et les travaux d'administration dans le monde Unix.

Exemple : il suffit de créer un nouvel utilisateur sur le serveur NIS pour que chaque machine client NIS ait accès aux informations de login de cet utilisateur.

 Les serveurs de noms - DNS

Comment relier les adresses IP utilisées pour acheminer les paquets aux noms utilisés par les utilisateurs ou les applications ?

Pour répondre à ce problème, on a créé DNS - Domain Name System, un annuaire distribué des adresses de l'Internet :

  • C'est une base de données distribuée qui est implantée dans une hiérarchie de serveurs de noms.
  • C'est un protocole applicatif, les hôtes, routeurs, serveurs de noms communiquent pour effectuer la traduction
  • Modèle Client/Serveur - un émetteur interroge un serveur de noms (serveur DNS) sur le port 53/UDP (ou 53/TCP pour les mises à jour).

 DNS - Les services

Permet la traduction d'adresses mais aussi d'autres services :

  • Host aliasing - donner un pseudonyme à une machine qui a un nom peu parlant
  • Mail server aliasing - un serveur Web et un serveur Mail peuvent avoir le même pseudonyme même s'ils n’ont pas la même adresse IP (2 machines)
  • La répartition de la charge - un nom de serveur Web ou Mail peut correspondre à plusieurs adresses IP (serveurs Web ou Mail répliqués) avec un système de rotation dans les réponses du serveur DNS

 

Une requête DNS peut impliquer plusieurs serveurs de noms répartis dans le monde entier.

Les problèmes d'un système centralisé

Tolérance aux pannes : si le serveur DNS tombe, tout l'Internet aussi !

La réponse soit la plus proche possible du demandeur

Trop de correspondances à gérer, nombre de requêtes au serveur trop importante.

Un système décentralisé

Serveurs de noms locaux à qui s'adressent les requêtes locales ; en charge de la résolution.

Serveurs de noms racine qui sont censés savoir comment s'approcher de la réponse.

Serveurs de noms de source autorisée qui contiennent les correspondances "officielles".

La notion de Domaine

Un domaine est un sous-arbre entier de l’espace de nommage.

Domaine complet

Domaine .fr

Domaine epsi.fr

Hôte ou noeud : ssh.epsi.fr

La notion de Zone

Une zone DNS est une portion d’un espace de noms de domaine gérée par une entité spécifique. Elle contient les enregistrements DNS (comme A, MX, CNAME, TXT) nécessaires pour traduire les noms de domaine en adresses IP et diriger le trafic réseau correctement.

Exemple :

La zone DNS de example.com peut inclure :

  • Un enregistrement A pour associer www.example.com à une adresse IP.
  • Un enregistrement MX pour gérer la messagerie (mail.example.com).

Chaque zone est gérée par un serveur DNS autoritaire, qui stocke et fournit ces enregistrements aux requêtes DNS.

Fonctionnement d'un DNS

Les enregistrements DNS

Les enregistrements DNS sont des entrées dans une zone DNS qui définissent comment un domaine est résolu et dirigé sur Internet. Chaque type d’enregistrement a un rôle spécifique.

  • A (Address) & AAAA - Associe un domaine à une adresse IPv4 ou à une adresse IPv6 (AAAA).
  • CNAME (Canonical Name) - Redirige un domaine vers un autre (alias).
  • MX (Mail Exchange) - Indique le serveur de messagerie.
  • TXT (Text) - Contient des informations textuelles (SPF/DKIM).
  • NS (Name Server) - Désigne les serveurs DNS autoritaires pour la zone.
  • PTR (Pointer) - Associe une adresse IP à un domaine (DNS inversé).
  • SRV (Service) - Définit l’emplacement d’un service spécifique (ex. VoIP).

Exemples d'enregistrements DNS

Clé Type Valeur
ssh.epsi.fr. CNAME backoffice.epsi.fr.
epsi.fr. NS ns.ovh.com.
epsi.fr NS ns2.ovh.com
epsi.fr. A 140.77.1.32
epsi.fr. MX 20 mx.ovh.com.
epsi.fr. MX 100 mx2.ovh.com.
backoffice.epsi.fr. A 140.77.1.67

Routage de courrier et DNS

Permet de centraliser la réception des messages sur une machine qui a un système plus robuste :

  • Anti-virus, anti-spam, …
  • Seule machine accessible sur le port 25 depuis l'extérieur via le pare-feu

Les MX permettent ensuite de répartir la charge sur différents serveurs de mail et de disposer de serveurs de secours, par exemple, en cas de saturation, le serveur SMTP peut aiguiller les messages via un autre serveur SMTP interne.

 

Ex : 20 mx.ovh.com. permet d'être plus prioritaire que 100 mx2.ovh.com.

Un annuaire fédérateur - LDAP

Un annuaire fédérateur LDAP - Lightweight Directory Access Protocol est un système de gestion et d'organisation d'informations, principalement utilisé pour centraliser des données telles que les utilisateurs, groupes, permissions et autres ressources dans un réseau.

  • Il permet de gérer des informations de manière hiérarchique et centralisée, facilitant l'authentification et l'autorisation des utilisateurs sur plusieurs systèmes.
  • Fédérateur signifie que l'annuaire peut intégrer des informations provenant de plusieurs sources ou domaines, unifiant ainsi les accès tout en gardant une gestion décentralisée.

Exemple d'utilisation de LDAP

Dans une entreprise, un annuaire LDAP fédérateur centralise les informations d'authentification (utilisateurs, groupes, permissions) provenant de plusieurs systèmes (messagerie, fichiers, intranet). Ainsi, un utilisateur n'a besoin que d'un seul identifiant et mot de passe pour accéder à tous les services, simplifiant l'administration et améliorant la sécurité.

L’administration de réseaux et le protocole SNMP

L'administration de réseaux consiste à gérer, configurer, surveiller et maintenir les équipements d'un réseau informatique (comme les routeurs, commutateurs, serveurs) afin d'assurer leur bon fonctionnement et leur sécurité.

SNMP - Simple Network Management Protocol est un protocole utilisé pour surveiller et gérer les équipements réseau. Il permet de récupérer des informations sur leur état (comme la charge CPU, l'utilisation de la bande passante) et d'effectuer des actions de configuration à distance.

Exemple d'utilisation de SNMP

Un administrateur réseau utilise SNMP pour surveiller la bande passante de son routeur. Grâce à des outils de gestion SNMP (comme Zabbix ou Nagios), il peut détecter une utilisation excessive de la bande passante, recevoir des alertes, et intervenir rapidement pour optimiser les performances du réseau.

Le courrier électronique

Les protocoles de courrier électronique permettent l’envoi, la réception et la gestion des e-mails entre les serveurs et les clients de messagerie.

Principaux types de protocoles :

  • SMTP (Simple Mail Transfer Protocol) : Utilisé pour l’envoi des e-mails depuis un client vers un serveur ou entre serveurs.
  • POP (Post Office Protocol) : Permet de télécharger les e-mails depuis un serveur vers un client, puis les supprime souvent du serveur. (Ex : POP3)
  • IMAP (Internet Message Access Protocol) : Permet de synchroniser les e-mails entre le serveur et plusieurs appareils, en laissant les messages stockés sur le serveur.
  • Webmail : Interface en ligne permettant d’accéder aux e-mails via un navigateur (ex. Gmail, Outlook Web).

Le web, protocole HTTP, serveur apache, caches Web

Nous verrons ça ensemble durant le module Services Web.

Architecture Client / Serveur d'un service IA.

3.

TP - Intégration Hugging Face

Intégrer Hugging Face dans un script NodeJS - 1

Nous voulons réaliser un script capable de synthétiser une grande quantité de texte en quelques phrases.

Créez un nouveau dossier "AI" puis à l'intérieur un dossier "TP".

Dans le dossier "TP" lancez la commande :

npm init

Puis nous allons ajouter le paquet dotenv pour utiliser des fichiers .env pour sauvegarder nos secrets :

npm i dotenv

Créez un fichier ".env" vide dans le dossier "TP".

Ensuite, ajoutez le code de la slide suivante dans un fichier "index.js".

Intégrer Hugging Face dans un script NodeJS - 2

require("dotenv").config();

async function queryModelWithFetch(inputText) {
  const MODEL_NAME = "facebook/bart-large-cnn";

  try {
    const response = await fetch(
      `https://api-inference.huggingface.co/models/${MODEL_NAME}`,
      {
        method: "POST",
        headers: {
          Authorization: `Bearer ${process.env.HF_API_TOKEN}`,
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          inputs: inputText,
        }),
      }
    );

    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const result = await response.json();
    return result;
  } catch (error) {
    console.error("Error:", error);
    throw error;
  }
}

async function main() {
  try {
    // Using Fetch
    const response = await queryModelWithFetch(
      "The tower is 324 metres (1,063 ft) tall, about the same height as an 81-storey building, and the tallest structure in Paris. Its base is square, measuring 125 metres (410 ft) on each side. During its construction, the Eiffel Tower surpassed the Washington Monument to become the tallest man-made structure in the world, a title it held for 41 years until the Chrysler Building in New York City was finished in 1930. It was the first structure to reach a height of 300 metres. Due to the addition of a broadcasting aerial at the top of the tower in 1957, it is now taller than the Chrysler Building by 5.2 metres (17 ft). Excluding transmitters, the Eiffel Tower is the second tallest free-standing structure in France after the Millau Viaduct."
    );
    console.log("Response:", response);
  } catch (error) {
    console.error("Main Error:", error);
  }
}

main();

Intégrer Hugging Face dans un script NodeJS - 3

Créez ensuite un compte sur Hugging Face pour pouvoir ensuite créer un token qui nous permettra de réaliser des requêtes sur certaines modèles. Lien vers la création d'un token.

Vous ne devez cocher que la case "Make calls to the serverless Inference providers". Une fois créé, ajouter la variable d'environnement "HF_API_TOKEN" avec la valeur du token.

Ensuite, ajoutez dans votre package.json, le script "start" qui aura pour valeur "node index.js".

Lancez la commande npm start.

Appelez-moi pour que l'on puisse vérifier ensemble.

Exercice 1 - Utiliser le modèle samLowe/roberta-base-go_emotions

Changer le modèle utilisé par notre script NodeJS par samLowe/roberta-base-go_emotions et relancer le script.

Que remarquez-vous ?

 

Maintenant, écrivez un message représentant une certaine émotion, relancez le script.

Que remarquez-vous ?

 

Appelez-moi pour que l'on puisse vérifier ensemble.

Exercice 2 - Utiliser le modèle deepseek-ai/DeepSeek-R1-Distill-Qwen-32B

Changer le modèle utilisé par notre script NodeJS par deepseek-ai/DeepSeek-R1-Distill-Qwen-32B et l'input par "Tell me a joke please.", relancez le script.

Que remarquez-vous ?

 

Essayez de l'utiliser comme vous feriez avec ChatGPT.

Que remarquez-vous ?

 

Appelez-moi pour que l'on puisse vérifier ensemble.

 30 minutes 

Soutenance

QCM

4.

Rendu TP et exercices

Je vais noter votre investissement durant nos séances.

Pour rendre votre travail, créez un dépôt sur Github ou Gitlab et ajoutez-moi en droit de lecture pour ValentinMontagne (Github) ou vm-marvelab (Gitlab) avec tous vos exercices et TPs.

 

Ajoutez dans un README votre nom / prénom pour que je puisse vous noter correctement.

 

N'oubliez pas le .gitignore pour éviter d'ajouter les node_modules.

N'hésitez pas à me donner votre avis.

Merci!