Ce projet utilise les SSE (Server-Sent Events) et Redis pour implémenter une salle de chat en ligne. Des connaissances préalables en syntaxe Python et JavaScript, ainsi qu'une compréhension de base de l'utilisation de Flask et de Redis, sont requises.
Dans cette partie de l'expérience, nous allons apprendre et pratiquer les concepts suivants :
Communication web en temps réel
Fonctionnement des SSE
Utilisation de Redis
👀 Aperçu
🎯 Tâches
Dans ce projet, vous allez apprendre :
Comment créer une simple salle de chat en ligne à l'aide de Flask et des SSE
Comment implémenter la fonctionnalité de connexion utilisateur
Comment utiliser Redis pour stocker et récupérer des messages
🏆 Réalisations
Après avoir terminé ce projet, vous serez capable de :
Configurer les SSE pour la communication en temps réel dans une application web
Utiliser Redis pour stocker et récupérer des messages dans une application de salle de chat
Implémenter la fonctionnalité de connexion utilisateur dans Flask
Communication web en temps réel
La Communication web en temps réel (WebRTC) fait référence à un mécanisme qui nous permet d'informer instantanément les utilisateurs d'un événement sur une page web sans qu'ils aient besoin de rafraîchir la page. Il existe de nombreuses utilisations de la WebRTC, telles que le chat en temps réel et les messages instantanés.
Il existe plusieurs manières de communiquer entre les clients web et les serveurs.
Flux HTTP classique
Le client demande une page web au serveur.
Le serveur répond en conséquence.
Le serveur renvoie la réponse au client.
Comme les requêtes HTTP sont sans état, ce qui signifie que la connexion HTTP est terminée après chaque requête, le serveur et le navigateur sont totalement ignorants l'un de l'autre jusqu'à la prochaine requête pour mettre à jour les informations pertinentes. À ce stade, il n'est pas difficile de concevoir une solution simple où le navigateur peut effectuer des requêtes périodiques pour simuler des effets en temps réel. Cela s'appelle le polling.
Flux de polling
Le client envoie une requête de connexion au serveur en utilisant HTTP classique.
Le client exécute un script de polling JavaScript intégré dans la page web pour envoyer périodiquement des requêtes au serveur (par exemple, toutes les 5 secondes) pour récupérer des informations.
Le serveur répond à chaque requête et renvoie les informations correspondantes, tout comme une requête HTTP normale.
Le polling nous permet d'obtenir des informations presque en temps réel. Cependant, les requêtes fréquentes du navigateur au serveur résultant du polling peuvent entraîner des inefficacités de performance. Pour atténuer ces problèmes, une méthode alternative a été proposée. Au lieu de répondre immédiatement aux requêtes du client, les serveurs attendent jusqu'à ce qu'il y ait un changement de données (ou un délai d'attente) avant de renvoyer une réponse. Cette approche maximise la validité de la connexion pour réduire le nombre de requêtes dans le polling. Cette méthode s'appelle le long polling, ou Long-Polling.
Flux de long polling
Le client demande une page web au serveur en utilisant HTTP classique.
Le client exécute un script JavaScript intégré dans la page web pour envoyer des données et demander des informations au serveur.
Au lieu de répondre immédiatement à la requête du client, le serveur attend une mise à jour valide.
Lorsque les informations sont mises à jour et valides, le serveur pousse les données au client.
Lorsque le client reçoit la notification du serveur, il envoie immédiatement une nouvelle requête pour initier la prochaine ronde de polling.
Les méthodes mentionnées ci-dessus sont couramment utilisées pour implémenter la communication web en temps réel. Cependant, après l'introduction d'HTML5, nous avons de meilleures options disponibles. En HTML5, nous pouvons utiliser les Server-Sent Events (SSE) ou le WebSocket. Les SSE sont spécifiquement conçus pour le transfert de données du serveur vers le client, ce qui est souvent suffisant pour des scénarios tels que la diffusion d'informations sur un match ou les changements de prix boursiers.
Flux des Server-Sent Events
Le client demande une page web au serveur en utilisant HTTP classique.
Le client établit une connexion avec le serveur en utilisant JavaScript intégré dans la page web.
Lorsque le serveur a des mises à jour, il envoie un événement au client.
Si les SSE ne répondent pas à nos besoins, nous pouvons utiliser le WebSocket à la place. Avec le WebSocket, un canal de communication bidirectionnel est établi entre le navigateur et le serveur, permettant un échange de messages bidirectionnels en temps réel, similaire à l'utilisation de sockets TCP.
Comparaison simple entre SSE et WebSocket
Le WebSocket est un canal de communication bidirectionnel qui prend en charge la communication bidirectionnelle et a des fonctionnalités plus avancées. Les SSE sont un canal unidirectionnel, où le serveur ne peut envoyer des données que vers le navigateur.
Le WebSocket est un nouveau protocole et nécessite une prise en charge côté serveur, tandis que les SSE sont déployés au-dessus du protocole HTTP et sont pris en charge par le logiciel serveur existant.
Les SSE sont un protocole léger et relativement simple, tandis que le WebSocket est un protocole plus lourd et relativement plus complexe.
Avec la compréhension de ces mécanismes pour implémenter la communication web en temps réel, nous allons maintenant utiliser les SSE pour implémenter une simple salle de chat en ligne.
Implémentation d'une salle de chat en ligne basée sur les SSE
Il existe diverses manières de pousser des messages dans une salle de chat en ligne, et dans ce cours, nous utiliserons les Server-Sent Events (SSE) pour y parvenir. Afin de faciliter la réception des messages, nous allons exploiter la fonctionnalité pub/sub (publish/subscribe) de Redis pour recevoir et envoyer des messages. Du côté du serveur web, nous utiliserons Flask pour l'implémentation.
Comment fonctionnent les SSE
Dans les leçons précédentes, nous avons appris que les SSE sont basées sur HTTP. Alors, comment le navigateur sait-il que ceci est un flux d'événements envoyés par le serveur? C'est en fait assez simple - il suffit de définir l'en-tête Content-Type de la requête HTTP sur text/event-stream. Les SSE consistent essentiellement en une requête HTTP envoyée par le navigateur au serveur, puis le serveur pousse continuellement des informations au navigateur de manière unidirectionnelle. Le format de ces informations est également très simple, avec le préfixe "data:" suivi du contenu du message, et se terminant par "\n\n".
Fonctionnalité pub/sub de Redis
Redis est une base de données en mémoire populaire qui peut être utilisée pour le caching, la file d'attente et d'autres services. Dans ce cours, nous utiliserons la fonctionnalité publish/subscribe de Redis. En bref, la fonctionnalité d'abonnement nous permet d'abonner à divers canaux, et chaque fois que de nouveaux messages sont publiés sur ces canaux, nous les recevons automatiquement. Lorsque le serveur reçoit un message envoyé par le navigateur via une requête POST, il publie ces messages sur des canaux spécifiques. Ensuite, les clients qui ont abonné à ces canaux reçoivent automatiquement ces messages, qui seront ensuite poussés vers les clients via les SSE.
Implémentation des fonctionnalités
Après l'analyse ci-dessus, le déroulement global de la salle de chat est désormais clair. Passons maintenant à l'implémentation des fonctionnalités de cette salle de chat.
Créez un fichier nommé app.py dans le répertoire ~/project et entrez le code source suivant :
import datetime
import flask
import redis
app = flask.Flask("labex-sse-chat")
app.secret_key = "labex"
app.config["DEBUG"] = True
r = redis.StrictRedis()
## Fonction de la route d'accueil
@app.route("/")
def home():
## Si l'utilisateur n'est pas connecté, redirigez-le vers la page de connexion
if "user" not in flask.session:
return flask.redirect("/login")
user = flask.session["user"]
return flask.render_template("index.html", user=user)
## Générateur de messages
def event_stream():
## Créez un système de publication-abonnement
pubsub = r.pubsub()
## Utilisez la méthode subscribe du système de publication-abonnement pour vous abonner à un canal
pubsub.subscribe("chat")
for message in pubsub.listen():
data = message["data"]
if type(data) == bytes:
yield "data: {}\n\n".format(data.decode())
## Fonction de connexion, la connexion est requise pour la première visite
@app.route("/login", methods=["GET", "POST"])
def login():
if flask.request.method == "POST":
## Stockez le nom d'utilisateur dans le dictionnaire de session puis redirigez vers la page d'accueil
flask.session["user"] = flask.request.form["user"]
return flask.redirect("/")
return flask.render_template("login.html")
## Recevoir les données envoyées par JavaScript en utilisant la méthode POST
@app.route("/post", methods=["POST"])
def post():
message = flask.request.form["message"]
user = flask.session.get("user", "anonymous")
now = datetime.datetime.now().replace(microsecond=0).time()
r.publish("chat", "[{}] {}: {}\n".format(now.isoformat(), user, message))
return flask.Response(status=204)
## Interface de flux d'événements
@app.route("/stream")
def stream():
## L'objet de retour de cette fonction de route doit être de type text/event-stream
return flask.Response(event_stream(), mimetype="text/event-stream")
## Exécutez l'application Flask
app.run()
Dans le code ci-dessus, nous utilisons la fonctionnalité de session de Flask pour stocker les informations de connexion de l'utilisateur, la fonctionnalité de publication-abonnement de Redis pour recevoir et envoyer des messages, et les SSE pour implémenter le poussage de messages.
Ici :
La fonction event_stream est un générateur de messages qui récupère continuellement des messages à partir de Redis et les pousse vers le client.
La fonction stream est une interface de flux d'événements qui renvoie un objet de type text/event-stream, qui est le flux d'événements SSE.
La fonction post est une interface qui reçoit les données envoyées par JavaScript en utilisant la méthode POST. Elle publie les données reçues sur le canal chat dans Redis.
La fonction login est une fonction de connexion qui est requise pour la première visite. Après une connexion réussie, le nom d'utilisateur est stocké dans le dictionnaire de session puis redirigé vers la page d'accueil.
La fonction home est la fonction de la route d'accueil. Si l'utilisateur n'est pas connecté, elle redirigera vers la page de connexion. Si l'utilisateur est connecté, elle affichera le modèle index.html.
Tout d'abord, créez un répertoire templates sous ~/project pour stocker les fichiers HTML requis. Dans le répertoire templates, créez un fichier login.html et écrivez le code suivant :
<!doctype html>
<title>Connexion à la salle de chat en ligne</title>
<style>
body {
max-width: 500px;
margin: auto;
padding: 1em;
background: black;
color: #fff;
font:
16px/1.6 menlo,
monospace;
}
</style>
<body>
<form action="" method="post">
Nom d'utilisateur : <input name="user" />
<input type="submit" value="connexion" />
</form>
</body>
Dans le fichier login.html, nous utilisons la fonctionnalité de modèle de Flask et utilisons {{ user }} pour représenter le nom de l'utilisateur, qui est récupéré à partir de flask.session.
Ensuite, créons un fichier index.html dans le répertoire templates pour implémenter la page de la salle de chat. Écrivez le code suivant dedans :
<!doctype html>
<title>Chat en ligne</title>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
<style>
body {
max-width: 500px;
margin: auto;
padding: 1em;
background: black;
color: #fff;
font:
16px/1.6 menlo,
monospace;
}
</style>
<p><b>Bonjour, {{ user }}!</b></p>
<p>Message : <input id="in" /></p>
<pre id="out"></pre>
<script>
function sse() {
// Se connecter au flux d'événements du serveur
var source = new EventSource("/stream");
var out = document.getElementById("out");
source.onmessage = function (e) {
out.innerHTML = e.data + "\n" + out.innerHTML;
};
}
// POST le message au serveur
$("#in").keyup(function (e) {
if (e.keyCode == 13) {
$.post("/post", { message: $(this).val() });
$(this).val("");
}
});
sse();
</script>
Dans le fichier index.html, nous utilisons la méthode $.post de jQuery pour envoyer des messages au serveur et utilisons EventSource pour recevoir les messages poussés par le serveur.
Comme Redis est utilisé, vous devez démarrer le service Redis dans votre environnement et télécharger le module redis nécessaire pour connecter Python au serveur Redis :
pip install redis
sudo service redis-server start
Ensuite, vous pouvez exécuter notre salle de chat :
cd ~/project
python app.py
Ensuite, vous pouvez accéder à http://localhost:5000 dans votre navigateur, entrer un nom d'utilisateur aléatoire et entrer dans la salle de chat.
Vous pouvez également ouvrir une autre fenêtre de navigateur en mode privé pour entrer dans la salle de chat, puis vous pouvez converser dans les deux fenêtres.
Sommaire
Ce projet utilise les SSE pour implémenter des fonctionnalités de communication web en temps réel et repose sur Flask et Redis pour créer une salle de chat en ligne. L'objectif est que chacun comprenne le processus de communication sous le protocole HTTP grâce à cette partie de l'expérience.
We use cookies for a number of reasons, such as keeping the website reliable and secure, to improve your experience on our website and to see how you interact with it. By accepting, you agree to our use of such cookies. Privacy Policy