Socket.io¶
Maintenant que nous avons une base avec un Hello World
, nous allons rajouter une fonctionnalité pour que vous puissiez mieux comprendre le fonctionnement de socket.io
dans cette application.
Avertissement
Dans cette section, nous verrons juste comment intégrer socket.io
à notre Hello World
pour que l’application reste bien structurée (le fonctionnement général de socket.io
étant expliqué sous pré-requis
).
Code côté serveur¶
Tout d’abord, nous allons créer un nouveau fichier nommé socket.js
que nous mettrons dans le dossier serveur
.
.
└── serveur
├── routes.js
└── socket.js
Dans ce fichier, nous écrivons le code suivant :
// comme dans le fichier routes.js, la fonction principale est lancée depuis app.js
// nous passons le paramètre io, qui contient le module socket.io, depuis app.js
exports.f = function(io) {
/* cette fonction de callback s'exécute à chaque fois qu'un client
émet l'événement "connection" */
io.on('connection', function (socket) {
/* lorsque le client effectue un socket.emit('bouton_client'),
cette fonction s'exécute */
socket.on('bouton_client', function(){
console.log('Le client a cliqué sur le bouton !')
});
});
}
Nous exécutons un require
pour que app.js
charge le module socket.io
:
var io = require('socket.io')(server);
Nous chargeons le fichier socket.js
:
var socket = require('./serveur/socket.js');
Puis, nous demandons à app.js
d’exécuter la fonction que nous venons de créer en lui passant le module socket.io
:
socket.f(io);
Votre fichier app.js
devrait alors ressembler à ceci :
var http = require('http');
var path = require('path');
var express = require('express');
// nous faisons appel à expressJS en tapant app.nom_de_la_fonction()
var app = express();
var server = http.Server(app);
var io = require('socket.io')(server);
var routes = require('./serveur/routes.js');
var socket = require('./serveur/socket.js');
// appel de la fonction qui se trouve dans "routes.js"
routes.f(app, __dirname);
// appel de la fonction qui se trouve dans "socket.js"
socket.f(io);
server.listen(8888);
Important
Il est essentiel de respecter l’ordre des require
. Comme vous pouvez le constater, certains modules dépendent d’autres modules. C’est par exemple le cas de socket.io
qui a besoin de la variable server
, qui nécessite elle-même la variable app
d’expressJS
pour fonctionner correctement. Si vous inversez l’ordre de ces instructions, des erreurs peuvent survenir.
Code côté client¶
Maintenant que le serveur peut faire fonctionner socket.io
, il reste quelques modifications à effectuer du côté client. Nous commençons par ajouter une ligne au début du fichier general.js
:
var socket = io.connect('http://' + window.location.host);
Astuce
window.location.host
contient le nom de domaine avec le port sur lequel est connecté le client. En l’occurence, cette commande équivaut à ceci :
var socket = io.connect('http://localhost:8888')
Ensuite, nous ouvrons un nouveau fichier pour séparer le javascript
du HTML
sur le côté client.
Question
Mais pourquoi ne pas utiliser general.js
?
Parce que ce fichier contient des fonctions javascript
qui s’appliquent à toutes les pages de l’application. Dans notre cas, le socket.emit
ne sert qu’à une seule page, index.ejs
. Il faudra donc plutôt créer un fichier du nom de index.js
:
Dans ce fichier, nous rédigeons une fonction avertit le serveur que le client a interagi avec la page web :
function avertir_serveur() {
socket.emit('bouton_client');
}
Ensuite, nous ajoutons un bouton qui exécutera cette fonction lorsqu’il sera cliqué sur la page index.ejs
:
<!-- la fonction avertir_serveur() s'exécute
lorsque nous cliquons sur ce bouton -->
<button class="btn btn-default" onclick="avertir_serveur()">
<span class="glyphicon glyphicon-link"></span>
Cliquez ici !
</button>
N’oublions pas de faire référence au fichier index.js
que nous venons de réaliser en ajoutant cette ligne juste avant la fin de la balise head
:
<script src="static/js/index.js"></script>
Notre page index.ejs
contient alors contenir ceci :
<!DOCTYPE html>
<html>
<head>
<% include balise_head %>
<script src="static/js/index.js"></script>
</head>
<body>
<% include barre_navigation %>
<div class="container">
<div class="row">
<div class="col-lg-offset-2 col-md-offset-1 col-md-10 col-lg-8">
<p>Hello World !</p>
<!-- la fonction avertir_serveur() s'exécute
lorsque nous cliquons sur le bouton -->
<button class="btn btn-default" onclick="avertir_serveur()">
<span class="glyphicon glyphicon-link"></span>
Cliquez ici !
</button>
<div class="col-lg-offset-2 col-md-offset-1"></div>
</div>
</div>
</body>
</html>
Astuce
Vous remarquerez que nous faisons référence au fichier index.js
juste après l’inclusion de la balise head
. Alors pourquoi ne pas mettre cette ligne dans le fichier balise_head
? Tout simplement parce que la page index.ejs
est la seule à avoir besoin de ce fichier. Il est donc inutile de demander aux autres pages de le charger alors qu’elles n’utilisent pas les fonctions que contient ce fichier.
Enfin, nous incluons le fichier socket.io.js
dans balise_head.ejs
pour que le client reconnaisse la fonction socket.emit()
:
<script src="/socket.io/socket.io.js"></script>
Avertissement
Cette balise doit apparaître avant l’appel de general.js
. Sinon, le navigateur ne trouvera pas la variable io
lors de l’exécution de l’instruction qui permet d’initier la connexion socket.io
entre le client et le serveur.
Résultat¶
Et voilà ! Maintentant, si nous relançons notre serveur, nous obtenons la page suivante :

En cliquant sur le bouton, un message s’affiche dans la console du serveur :
Le client a cliqué sur le bouton !
Le client a cliqué sur le bouton !
...
Astuce
Vous pouvez télécharger le contenu du programme actuel en cliquant ici.