WebSockets - Communication avec le serveur

Le Web a été en grande partie construit autour du paradigme requête / réponse de HTTP. Un client charge une page Web et rien ne se passe jusqu'à ce que l'utilisateur clique sur la page suivante. Vers 2005, AJAX a commencé à rendre le Web plus dynamique. Pourtant, toutes les communications HTTP sont dirigées par le client, ce qui nécessite une interaction de l'utilisateur ou une interrogation périodique pour charger de nouvelles données à partir du serveur.

Les technologies qui permettent au serveur d'envoyer les données à un client au moment même où il sait que de nouvelles données sont disponibles existent depuis un certain temps. Ils portent des noms tels que"Push" ou “Comet”.

Avec long polling, le client ouvre une connexion HTTP au serveur, ce qui la maintient ouverte jusqu'à l'envoi de la réponse. Chaque fois que le serveur a réellement de nouvelles données, il envoie la réponse. Les sondages longs et les autres techniques fonctionnent assez bien. Cependant, tous partagent un problème, ils supportent la surcharge de HTTP, ce qui ne les rend pas bien adaptés aux applications à faible latence. Par exemple, un jeu de tir multijoueur dans le navigateur ou tout autre jeu en ligne avec un composant en temps réel.

Apporter des sockets sur le Web

La spécification Web Socket définit une API établissant des connexions "socket" entre un navigateur Web et un serveur. En termes simples, il existe une connexion persistante entre le client et le serveur et les deux parties peuvent commencer à envoyer des données à tout moment.

La connexion Web socket peut être simplement ouverte à l'aide d'un constructeur -

var connection = new WebSocket('ws://html5rocks.websocket.org/echo', ['soap', 'xmpp']);

wsest le nouveau schéma d'URL pour les connexions WebSocket. Il y a aussiwss, pour une connexion WebSocket sécurisée de la même manière https est utilisé pour les connexions HTTP sécurisées.

Le fait d'attacher immédiatement certains gestionnaires d'événements à la connexion vous permet de savoir quand la connexion est ouverte, a reçu des messages entrants ou en cas d'erreur.

Le deuxième argument accepte facultatif subprotocols. Il peut s'agir d'une chaîne ou d'un tableau de chaînes. Chaque chaîne doit représenter unsubprotocol le nom et le serveur n'acceptent qu'un seul des subprotocolsdans le tableau. Acceptésubprotocol peut être déterminé en accédant à la propriété de protocole de l'objet WebSocket.

// When the connection is open, send some data to the server
connection.onopen = function () {
   connection.send('Ping'); // Send the message 'Ping' to the server
};

// Log errors
connection.onerror = function (error) {
   console.log('WebSocket Error ' + error);
};

// Log messages from the server
connection.onmessage = function (e) {
   console.log('Server: ' + e.data);
};

Communiquer avec le serveur

Dès que nous avons une connexion au serveur (lorsque l'événement open est déclenché), nous pouvons commencer à envoyer des données au serveur en utilisant la méthode send (your message) sur l'objet de connexion. Auparavant, il ne prenait en charge que les chaînes, mais dans la dernière spécification, il peut désormais également envoyer des messages binaires. Pour envoyer des données binaires, un objet Blob ou ArrayBuffer est utilisé.

// Sending String
connection.send('your message');

// Sending canvas ImageData as ArrayBuffer
var img = canvas_context.getImageData(0, 0, 400, 320);
var binary = new Uint8Array(img.data.length);

for (var i = 0; i < img.data.length; i++) {
   binary[i] = img.data[i];
}

connection.send(binary.buffer);

// Sending file as Blob
var file = document.querySelector('input[type = "file"]').files[0];
connection.send(file);

De même, le serveur peut nous envoyer des messages à tout moment. Chaque fois que cela se produit, le rappel onmessage se déclenche. Le rappel reçoit un objet événement et le message réel est accessible via la datapropriété.

WebSocket peut également recevoir des messages binaires dans la dernière spécification. Les trames binaires peuvent être reçues au format Blob ou ArrayBuffer. Pour spécifier le format du binaire reçu, définissez la propriété binaryType de l'objet WebSocket sur «blob» ou «arraybuffer». Le format par défaut est «blob».

// Setting binaryType to accept received binary as either 'blob' or 'arraybuffer'
connection.binaryType = 'arraybuffer';
connection.onmessage = function(e) {
   console.log(e.data.byteLength); // ArrayBuffer object if binary
};

Les extensions sont une autre fonctionnalité nouvellement ajoutée de WebSocket. En utilisant des extensions, il sera possible d'envoyer des trames compressées, multiplexées, etc.

// Determining accepted extensions
console.log(connection.extensions);

Communication cross-origine

Étant un protocole moderne, la communication cross-origin est directement intégrée à WebSocket. WebSocket permet la communication entre les parties sur n'importe quel domaine. Le serveur décide de rendre son service disponible à tous les clients ou uniquement à ceux qui résident sur un ensemble de domaines bien définis.

Serveurs proxy

Chaque nouvelle technologie s'accompagne d'un nouvel ensemble de problèmes. Dans le cas de WebSocket, c'est la compatibilité avec les serveurs proxy, qui assure la médiation des connexions HTTP dans la plupart des réseaux d'entreprise. Le protocole WebSocket utilise le système de mise à niveau HTTP (qui est normalement utilisé pour HTTP / SSL) pour «mettre à niveau» une connexion HTTP vers une connexion WebSocket. Certains serveurs proxy n'aiment pas cela et abandonneront la connexion. Ainsi, même si un client donné utilise le protocole WebSocket, il peut ne pas être possible d'établir une connexion. Cela rend la section suivante encore plus importante :)

Le côté serveur

L'utilisation de WebSocket crée un tout nouveau modèle d'utilisation pour les applications côté serveur. Alors que les piles de serveurs traditionnelles telles que LAMP sont conçues autour du cycle de requête / réponse HTTP, elles ne gèrent souvent pas bien un grand nombre de connexions WebSocket ouvertes. Garder un grand nombre de connexions ouvertes en même temps nécessite une architecture qui bénéficie d'une forte concurrence à un faible coût de performance.