Débuter avec Node.js partie 3

Première application Node.js et HTML5
Date de publication : 14 mars 2012.
ParRomain Maton
Introduction Installation Arborescence Client Serveur Run baby ! Conclusion et remerciements Introduction

Socket.IO
Pour ce
Quick Start, je vous propose une application qui fera du
pushsur tous les clients pour leur envoyer l'heure système ainsi que le nombre de clients actuellement connectés au serveur (avec gestion de la déconnexion). Ces clients pourront envoyer des
pokesaux autres clients, le tout tournera avec
expresset
Socket.IO.
L'idée n'est pas de développer une application de gestion complète (qui mériterait une bonne dizaine de billets) ni de faire un tour d'horizon de la centaine de bibliothèques existantes, mais juste de vous montrer à quoi ressemble le code d'une application Node avec deux bibliothèques très répandues dans la communauté.
Installation
Dès lors, vous n'avez plus que deux commandes à effectuer pour installer les modulesexpressetSocket.IOpour Node :
Vous voilà prêt, commençons tout de suite !
Arborescence
Le projet aura l'arborescence suivante :
Très simple donc avec un fichierserver.jset dans un dossierpublic, un fichierindex.html.
Client
Tout d'abord, voyons le squelette du fichier HTML :
Un fichier très standard donc, avec un import du dernier jQuery, l'import de Socket.IO (module chargé par Node) et quelquesdivqui me permettront d'afficher les retours du serveur.
À la suite des deux balisesscript déjà présentes, je rajoute le code JavaScript suivant :
Quelques explications :
- tout d'abord, je crée un objectio.Socket (qui par défaut utilisera lehostd'entrée et le port 80) ;
- lorsque le serveur m'envoie un message, je peux le récupérer côté client en utilisant le code suivant (API Socket.IO) :sock.on('message', function(data) {...});;
- le serveur me renverra un objet JSON, je le parcours et récupère les propriétésmessageoutimestampetclientque je mets dans les champs associés ;
- je connecte la socket immédiatement après ;
- je définis un gestionnaire d'événement sur le bouton et lors d'un clic utilisateur, j'envoie un messagepoke.
Plutôt simple non ? Même si l'API standard est déjà très simple d'utilisation, Socket.IO nous simplifie encore plus l'utilisation deWeb Socketscôté client et côté serveur.
Voyons maintenant le code côté serveur.
Serveur
Et voici le fichierserver.js:
Dans le détail :
- j'importe les modulesSocket.IOetexpress;
- je crée le serveurexpress, je configure le dossierpublicen statique, jemappel'URL racine'/' vers le fichierindex.htmlet je démarre le serveur ; on voit ici queexpressnous simplifie grandement le mapping entre une URL et une action (mais il n'est pas le seul) avec une bonne gestion des paramètres, j'aime beaucoup cette bibliothèque car elle me rappelle le très puissantSpring MVC;
- je crée ensuite l'objetsocketen spécifiant quelques transports et en supprimant leflash policy server(inutile pour notre exemple) ;
- lorsqu'un client se connecte, je le stocke dans un objet JSON, j'augmente la variableidet j'augmente le nombre de clients connectés (variableallClients) ;
- je lance unsetIntervalpour envoyer toutes les secondes l'heure courante du serveur ainsi que le nombre de clients connectés (le JSON qui sera récupéré dans mon client,cf.code du § client) ;
- si un client envoie un message côté serveur, je le répercute à tous les autres avec un message générique mentionnant l'iddu client qui a envoyé le message ;
- enfin, sur une déconnexion d'un client, je stoppe lesetIntervallié à ce client et je décrémente la variableallClients; celle-ci sera ensuite envoyée à tous les autres clients lors d'un prochain envoi de données dusetInterval.
Il y a bien sûr différentes manières de faire ce code, celui-ci ne sert qu'à vous montrer ce que l'on peut faire :
- envoyer un message à un client spécifique ;
- renvoyer un message d'un client vers tous les autres ;
- mettre à jour des variables globales utilisées par tous les clients ;
- …
D'ailleurs, si vous avez d'autres astuces concernant lesWeb Socketsdans Node, n'hésitez pas à les partager en commentaires !
Run baby !
Et maintenant, amusez-vous à lancer plusieurs navigateurs à cette URL, à envoyer despokes, à vous déconnecter…
Ir Christian BAGALWA
rmat0n:~$ brew install node rmat0n:~$ curl http://npmjs.org/install.sh | sudo sh |
rmat0n:~$ npm install express rmat0n:~$ npm install socket.io |
/ project / public index.html server.js |
<html> <head> <title>Socket IO Demo</title> <script src="http://code.jquery.com/jquery-1.5.min.js"></script> <script src="/socket.io/socket.io.js"></script> </head> <body> <div> <h2>Démo Node.js + Socket IO</h2> <label for="timestamp">Timestamp</label> <div id="timestamp"></div> <label for="clients">Clients</label> <div id="clients"></div> <label for="message">Message</label> <div id="message"></div> <p><button id="poke">Send poke !</button></p> </div> </body> </html> |
<script type="text/javascript"> $(document).ready(function () { var sock = new io.Socket(); sock.on('message', function (data) { var obj = JSON.parse(data); if(obj.message) { $('#message').text(obj.message); } else { $('#timestamp').text(obj.timestamp); $('#clients').text(obj.clients); } }); sock.connect(); $("#poke").click(function() { sock.send("Poke !"); }); }); </script> |
var io = require('socket.io'); var express = require('express'); var app = express.createServer(); app.configure(function(){ app.use(express.static(__dirname + '/public')); }); app.get('/', function(req, res, next){ res.render('./public/index.html'); }); app.listen(8333); var socket = io.listen(app, { flashPolicyServer: false, transports: ['websocket', 'flashsocket', 'htmlfile', 'xhr-multipart', 'xhr-polling', 'jsonp-polling'] }); var allClients = 0; var clientId = 1; socket.on('connection', function(client) { var my_timer; var my_client = { "id": clientId, "obj": client }; clientId += 1; allClients += 1; my_timer = setInterval(function () { my_client.obj.send(JSON.stringify({ "timestamp": (new Date()).getTime(), "clients": allClients })); }, 1000); client.on('message', function(data) { my_client.obj.broadcast(JSON.stringify({ message: "poke send by client "+my_client.id })); console.log(data); }); client.on('disconnect', function() { clearTimeout(my_timer); allClients -= 1; console.log('disconnect'); }); }); |
rmat0n:~/dev/node-example$ node server.js |