Dans cet article nous vous présentons un exemple d’application p5js en réseau.
Ici, les utilisateurs peuvent contribuer à un même dessin en direct.
Cet exemple expliqué en détail doit vous permettre de comprendre les bases d’un telle solution pour développer votre propre application.
Structure de notre application
Notre projet se compose des répertoires et fichiers suivants :

Les fichiers server.js et package.js sont spécifiques au serveur tournant sous node.js.
- package.js défini les modules à installer (ici express et socket.io)
- server.js défini les actions réalisées par le serveur
Le répertoire public contient tous les fichiers utilisés par la partie client.
Ce sont les fichiers « servis » par le serveur node.js , accessibles depuis un navigateur.
- index.html est le fichier « servi » par défaut.
- sketch.js est notre fichier sketch p5js associé à index.html
Architecture du serveur
Notre serveur va « servir » via le module express le fichier index.html présent dans le répertoire public, et va permettre la
communication avec le client grâce au module socket.io.
Comment cela fonctionne-t-il ?
Remarque : Pour bien comprendre le fonctionnement de cet application client/serveur, il est conseillé de regarder attentivement les programmes server.js et sketch.js et les commentaires associés en même temps que ces explications.
Sans rentrer dans le détail, la bibliothèque socket.io met à disposition un ‘module’ io qui se trouve au niveau supérieur et qui gère toutes les communications. On trouve ensuite les sockets (prises en anglais) qui permettent de créer un canal de communication entre le client et le serveur. Un socket défini un port (une « porte ») par lequel vont transiter les messages.On peut représenter ce système de communication à l’aide du schéma suivant:
Le schéma ci-dessous donne une idée du fonctionnement de notre application client/serveur.
C’est le client, avec l’instruction socket = io() présente dans sketch.js qui fait une demande de création d’un « canal de communication » au serveur. Il envoi en fait un paquet demande de ‘connection’ au serveur.
L’instruction io.on(‘connection’,newConnectionProcess) présente au niveau du serveur (server.js) permet à celui-ci de créer un canal de communication avec le client suite à une demande de ‘connection’ mais également de lui indiquer comment gérer les messages arrivants sur le socket associé (function onMouseMsgReceived).
Voilà ! la communication est établie via les sockets entre le client et le serveur.
Ces derniers vont pouvoir communiquer à l’aide de message. Ces messages
qui vont transiter via le réseau se composent (en simplifiant) des
éléments suivants :
Dans la suite nous n’allons nous intéresser qu’à la partie :
Notre application de dessin collaboratif doit permettre aux
différents utilisateurs d’indiquer aux autres les tracés qu’ils font sur
leur écran. Pour cela ils vont envoyer au serveur les coordonnées
successives de leur souris.
Pour distinguer les messages des uns des autres, il est nécessaires de les caractérisés par un tag spécifiques.
Ici notre message sera défini comme étant de type « mouse » et
les données seront composées des 2 valeurs correspondant aux
coordonnées de la souris : var data = { x : mouseX, y : mouseY };
Pour info, dans socket.io on ne parle pas de type mais plutôt d’évènement « mouse » car, en effet, à la réception du message celui-ci va être traité comme un évènement : ‘un message de type « mouse » vient d’arriver’.
Pour envoyer ce message, le client utilise l’instruction : socket.emit(‘mouse’,data);
Au niveau du serveur rappelons nous que nous avons défini une
fonction newConnectionProcess qui indique au serveur ce qu’il doit faire à la
réception d’un message.
Dans cette fonction, nous trouvons l’instruction: socket.on(‘mouse’,function onMouseMsgReceived (data) {...});
qui indique via la fonction onMouseMsgReceived comment gérer la réception d’un message de type ‘mouse’.
function onMouseMsgReceived(data) {
socket.broadcast.emit(‘mouse’,data);
};
A la réception d’un message :
le module socket.io appelle la fonction onMouseMsgReceived en lui
passant en paramètre la partie donnée (data) du message. Celle-ci émet à
nouveau le message à destination de tous les autres clients grâce à
l’instruction socket.broadcast.emit(‘mouse’,data).
Ici, le serveur sert uniquement de relai et renvoi le même message. On
peut bien évidemment envoyer le type de message et les données de son
choix.
Il ne nous reste plus qu’à détailler ce qui se passe côté client à la
réception du message ‘mouse’ envoyé par le serveur. En fait, le client
grâce à l’instruction socket.on(‘mouse’,function onMouseMsgReceived(data) {...}); exécute la fonction onMouseMsgReceived en lui passant en paramètre la partie donnée du message qui correspond aux cordonnées de la souris (data).
Ici, il s’agit d’un regroupement de données, la valeur de x et de y.
Afin de pouvoir les distinguer elles sont stockées sous forme d’un objet
composé de 2 propriétés x et y. Pour y accéder il suffit d’utiliser la
notation data.x et data.y.
Serveur et envoi de messages
Il faut savoir que le serveur peut envoyer un message aux clients selon trois modes :
- socket.emit(‘msg2’, data2); // envoi sur le socket du client courant et lui seul.
- io.emit(‘msg2’, data2); // envoi à tous les clients y compris l’émetteur.
- socket.broadcast.emit(‘msg2’, data2); // envoi à tous les clients sauf l’émetteur.
Ci-dessous les schémas illustrant chacun de ces 3 modes :
Envoi sur le socket du client courant et lui seul :
Envoi à tous les clients y compris l’émetteur :
Envoi à tous les clients sauf l’émetteur :
Les fichiers principaux
fichers sketch.js
(
Christophe Béasse - Octobre 2017 )