Fermer
DéveloppementOutils - Conseils

HTML5 WebSockets, le successeur du protocole HTTP ?

J’ai lu récemment un article concernant le succès des Websockets ! Qu’est-ce ? En quoi est-il différent du protocole HTTP ? Comment fonctionne t-il ? Je vais tenter de répondre à toutes ces questions dans la suite de cet article, en présentant dans un premier temps les limites d’HTTP, puis analyser le protocole WebStocket et son API.

Histoire

Au cours des quinze dernières années, les applications Web ont progressivement remplacé celles fondées sur d’autres protocoles réseau. Mais il y a une lacune majeure dans le protocole de transfert HTTP (Hypertext Transfer Protocol) utilisé pour communiquer sur le Web. En effet, ce dernier a été initialement conçu pour fournir des documents et des fichiers simples pour les navigateurs Web, mais pas pour une interaction complexe en temps réel.

Dans le cadre du protocole HTTP, un client tel un navigateur Web, doit ouvrir une connexion sur un serveur, faire une demande, attendre une réponse, et fermer la connexion. Si le client souhaite d’avantages d’informations, il doit ouvrir une nouvelle connexion. C’est comme de raccrocher le téléphone et recomposer le numéro après chaque phrase de conversation. Et si le serveur possède de nouvelles informations pour le client, il doit attendre la demande du client plutôt que de l’envoyer sur le coup.

Cette redondance n’économise pas la bande passante. Pire encore, elle rend presque impossible qu’un client Web garde un maximum d’informations à la seconde près. Dans certaines situations, telles que la finance, les millisecondes perdues peuvent signifier des occasions manquées, et de fait, une perte d’argent.

Depuis des années, les développeurs Web n’ont pas hésité à hacker le protocole, retranchant ainsi les limites d’HTTP avec des techniques de programmation tels que Comet. Ce dernier retarde la fermeture d’une connexion HTTP afin de transmettre plus de données, ainsi le serveur Web peut envoyer des informations au navigateur Web sans que celui-ci l’ait explicitement demandé.
Mais ce que les développeurs souhaitent vraiment, c’est une connexion entre le client et le serveur qui reste ouverte indéfiniment, permettant aux deux parties d’envoyer des données dans les deux sens si nécessaire.

Le standard HTML5, permet pour les applications Web actuelles, de soutenir ce nouveau protocole appelé WebSockets. Ce dernier permet à un client Web de créer une connexion, la maintenir ouverte tant qu’il veut, et à la fois envoyer et recevoir des données en continu.

Le protocole WebSockets

Cette spécification permet donc d’ouvrir une connexion bi-directionnelle permanente entre un client et un serveur, afin de résoudre certains problèmes posés par le caractère unidirectionnel et déconnecté du protocole HTTP que nous avons vu précédemment.

Dans quel but ? Le développement de ce protocole permet le développement de véritables applications temps-réel performantes (informations, bourses, chat, jeux en ligne …).

La spécification des WebSockets, définie dans le standard HTML5, est développée par le W3C, tandis que le protocole de communication est standardisé par l’IETF (Internet Engineering Task Force).

Votre navigateur accède à une page Web et charge, disons, une application JavaScript. Cette dernière décide qu’elle a besoin d’un flux constant de données. La requête de type “upgrade” doit être envoyée par le client, afin de demander la mise à jour de la connexion TCP/HTTP actuelle vers le mode WebSocket, ressemblant à ceci :

[sourcecode language=”bash”]
GET /text HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: www.example.com
Origin: http://example.com
WebSocket-Protocol: sample
Sec-WebSocket-Version: 6

[/sourcecode]

Le serveur vous répondant :

[sourcecode language=”bash”]
HTTP/1.1 101 WebSocket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: http://example.com
WebSocket-Location: ws://example.com/demo
WebSocket-Protocol: sample

[/sourcecode]

Cet échange initial, de la demande et de la réponse, est nommé “handshake” et vient effectuer la communication entre le serveur et le client. Les détails du protocole se trouvent sur le site de l’IETF. Dans l’exemple présenté ci-dessus la version du protocole date du 25 février 2011 et numérotée 06.

Note : Je précise que ces publications sont en état de “brouillon” et changent constamment.

Le client et le serveur peuvent envoyer librement des données à l’autre par ce protocole. Il partage le port HTTP avec le contenu existant, traversant facilement les différents pare-feu, routeurs, proxy, etc… Cette technologie est couramment appelée méthode Push. Le serveur vient pousser (push) les données vers le client et n’est pas obligé d’attendre que ce dernier ne demande l’information.

HTML5 WebSockets, le successeur du protocole HTTP ? - WebSocket architecture

L’utilisation de l’API WebSocket

L’API, développée par le W3C, introduit l’interface WebSocket suivante :

[sourcecode language=”bash”]
[Constructor(in DOMString url, in optional DOMString protocols)]
[Constructor(in DOMString url, in optional DOMString[] protocols)]
interface WebSocket {
readonly attribute DOMString url;

const unsigned short CONNECTING = 0;
const unsigned short OPEN = 1;
const unsigned short CLOSING = 2;
const unsigned short CLOSED = 3;

readonly attribute unsigned short readyState;
readonly attribute unsigned long bufferedAmount;

attribute Function onopen;
attribute Function onmessage;
attribute Function onerror;
attribute Function onclose;

readonly attribute DOMString protocol;

void send(in DOMString data);
void close();
};
WebSocket implements EventTarget;
[/sourcecode]

En fournissant une API native qui ne nécessite pas de “bidouille” à base de requêtes Ajax ou d’iframe pour gérer les notifications du serveur, les WebSocket tentent donc de fournir un cadre standard pour les applications Comet.

Ainsi pour créer une instance de WebSocket, le seul argument qu’on doit fournir est l’URL du serveur avec lequel on souhaite établir une liaison. Elle commence obligatoirement par ws:// (ou wss:// pour une connexion sécurisée).

  • WebSocket – ws://www.websocket.org/text
  • WebSocket Secure – wss://www.websocket.org/encrypted-text

Ensuite, l’interface comporte les attributs fonctionnels permettant de gérer les évènements associés:

  • onopen : ouverture d’une WebSocket
  • onmessage : réception d’un message
  • onerror : erreur(s) survenue(s)
  • onclose : fermeture de WebSocket

Les messages envoyés par le serveur sont notifiés par l’événement onmessage contenant le message du serveur sous forme de chaîne. Les événements onerror, onopen et onclose permettent de suivre en temps réel l’état de la connexion.

Les WebSocket fournissent deux méthodes :

  • send( data_string) pour envoyer un message au serveur
  • close() pour fermer la socket

Une fois la connexion établie en mode WebSocket, les données peuvent être envoyées et reçues entre le client et le serveur en mode full-duplex.

Les données sont envoyées dans des iframes, où chaque iframe commence par un octet 0×00 et se termine avec un octet 0xFF. Entre le début et la fin, elle contient des données UTF-8, comme :

[sourcecode language=”bash”]
\x00Bonjour, bienvenue dans le monde des WebSockets\0xff
[/sourcecode]

Aucune limite n’est définie pour la taille des données qui peuvent être envoyées, et ce, aussi longtemps que le client puisse les gérer. En JavaScript, la limite est fixée par le langage, qui ne permet pas d’envoyer plus de 4 Go de données.
Avec le protocole WebSocket, chaque paquet de données possède seulement une enveloppe de 2 octets, le gain est donc faible par rapport à l’entête dans une requête HTTP et l’entête de la réponse.

Support

Implémentation côté serveur

À ce jour, il existe différents serveurs WebSocket disponibles et le meilleur du lot est sans doute le Kaazing WebSocket Gateway.

HTML5 WebSockets, le successeur du protocole HTTP ? - Kaazing WebSocket Gateway

PS : Une copie d’évaluation de la même chose peut être téléchargée à partir www.kaazing.com.

De nombreux projets sont en cours pour créer d’autres serveurs et frameworks intégrant les WebSockets.

Implémentation côté client : navigateurs

Au début de son implémentation il y avait des doutes quant à l’avenir des WebStockets au sein d’HTML5. Mais à la suite d’implication des principaux acteurs des navigateurs, tels que Microsoft, Google, Mozilla et Apple, l’avenir s’est clairement éclairci. Les navigateurs supportant le protocole WebSocket dès maintenant sont les suivants :

  • Chrome (version 4+)
  • Firefox (version 4+)
  • Opéra (version 11+ mais désactivé)
  • Safari (version 5+)

Pour ce qui est d’Internet Explorer aujourd’hui rien n’est fait, mais je ne sais pas ce que l’avenir nous réserve…

Il y a deux façons de vérifier si votre navigateur prend en charge ou non le protocole WebSocket. La première façon est de simplement aller sur le site www.websocket.org et vérifier dans ​​le côté en haut à droite le message indiquant que votre navigateur supporte ou non les WebSockets.

HTML5 WebSockets, le successeur du protocole HTTP ? - Invalidité de Firefox 4 sous MacOSX
HTML5 WebSockets, le successeur du protocole HTTP ? - Validité des websockets de Chrome sous MacOSX

La deuxième façon est d’écrire un code JavaScript simple et vérifier vous-même :

[sourcecode language=”JavaScript”]
if (window.WebSocket) {
alert("Félicitation !! Votre navigateur supporte le protocole WebSocket.");
} else {
alert("Désolé !! Votre navigateur ne supporte pas le protocole WebSocket.");
}
[/sourcecode]

Le manque de support des navigateurs est principalement dû à des failles de sécurité dans la spécification du protocole, que je détaillerais dans la prochaine section.

Voyons maintenant comment il est facile d’utiliser l’objet WebSocket.

Mise en application

Voici un exemple de WebSocket relativement simple :

[sourcecode language=”JavaScript”]
window.onload = function() {
if (!window.WebSocket) {
alert("Désolé !! Votre navigateur ne supporte pas le protocole WebSocket.");
} else {
socket.load();
}
}

socket = {
_ws: null,
load: function() {
var location = ‘ws://localhost/socket’
this._ws = new WebSocket(location);
this._ws.onopen = this._onopen;
this._ws.onmessage = this._onmessage;
this._ws.onclose = this._onclose;
},

_onopen: function() {
alert(‘Socket ouvert !’);
},
_onclose: function() {
alert(‘Socket fermé !’);
this._ws = null;
},
_onmessage: function(m) {
alert(‘Je viens de recevoir un message : ‘ + m.data);
}
}
[/sourcecode]

Analysons le code ci-dessus.

[sourcecode language=”JavaScript”]
window.onload = function() {
if (!window.WebSocket) {
alert("Désolé !! Votre navigateur ne supporte pas le protocole WebSocket.");
} else {
socket.load();
}
}
[/sourcecode]

Au chargement de la page, nous initialisons l’objet socket que nous créons ensuite, seulement et seulement si le navigateur supporte les WebSockets, sinon nous chargeons la suite.

[sourcecode language=”JavaScript”]
load: function() {
var location = ‘ws://localhost/socket’
this._ws = new WebSocket(location);
this._ws.onopen = this._onopen;
this._ws.onmessage = this._onmessage;
this._ws.onclose = this._onclose;
}
[/sourcecode]

Lorsque l’on appelle cette méthode, on initialise le WebSocket. Pour cela, on définit son URL (location). Ensuite, on crée l’objet WebSocket et on le stocke dans une variable de classe afin de le récupérer et l’utiliser par la suite.

Puis, on gère les événements survenus suite à la création. Chaque objet WebSocket possède quelques fonctions callbacks (onopen, onmessage , onclose, onerror), comme nous l’avons vu précédemment.

On appelle ces méthodes, à l’intérieur des méthodes internes à notre objet socket.

[sourcecode language=”JavaScript”]
_onopen: function() {
alert(‘Socket ouvert !’);
}
[/sourcecode]

Dans le cadre de notre test, nous allons informer l’utilisateur que notre socket a bien été ouvert.

[sourcecode language=”JavaScript”]
_onclose: function() {
alert(‘Socket fermé !’);
this._ws = null;
}
[/sourcecode]

Enfin, dernière étape de notre socket, nous allons le fermer libérant ainsi la mémoire.

[sourcecode language=”JavaScript”]
_onmessage: function(m) {
alert(‘Je viens de recevoir un message : ‘ + m.data);
}
[/sourcecode]

A chaque fois qu’un message est envoyé, on affiche celui-ci à l’utilisateur :

HTML5 WebSockets, le successeur du protocole HTTP ? - Résultat JavaScript de la réception d'un message

Comme vous pouvez le voir, utiliser les sockets en eux même n’est pas très difficile.

Sécurité

De nombreuses études ont été menées par des experts de la sécurité concernant l’utilisation des WebSockets. À la suite de ces études un rapport a été effectué présentant que des failles importantes aient été découvertes, notamment la possibilité d’empoisonnement de cache URL (cache-poisoning) dans des cas de présence de proxys transparents. Le but de cette faille est d’usurper l’URL d’un site vulnérable en affichant une page malicieuse identique tout en conservant l’url du site visé.

Suite à ces études, les navigateurs Opéra et Firefox ont décidé de désactiver leur support des WebSockets (qui peut être réactivé dans les options) jusqu’à la résolution de ces problèmes dans une future version.

Conclusion

Le protocole WebSocket représente une avancée très importante dans la communication client-serveur. Le protocole HTTP, non connecté et sans état, qui historiquement n’avait pas été prévu pour établir des connexions permanentes ni le push de données, semble être dépassé… Bien-entendu, plusieurs techniques ont été développées pour contourner ces problèmes et permettre la réception des données mises à jour quasi-instantanément (polling, long-polling…), mais celles-ci surchargent le réseau avec des headers HTTP inutiles. Les WebSocket permettront bientôt d’y remédier.

Par contre, la spécification est encore jeune et ne bénéficie pas pour le moment d’un large support parmi les navigateurs. Outre le navigateur, les WebSockets posent aussi un problème d’infrastructure puisqu’il ne s’agit plus seulement de fournir un serveur HTTP mais plutôt un serveur WebSocket. Il existe déjà quelques solutions serveur, tel que Kazzing (énoncé ci-dessus), mais l’offre est encore très réduite et expérimentale. Les WebSockets ne sont pas exclusifs à Kaazing. Google a été un des premiers défenseurs. Outre la construction de la technologie dans son navigateur Chrome, la firme prend en charge un site qui montre aux développeurs comment le mettre en œuvre.

Il faudra attendre encore quelque temps avant de pouvoir bénéficier de serveurs WebSocket éprouvés. De plus, la faible implémentation des WebSockets rend leur utilisation assez difficile pour le moment. Enfin, même constat avec les problèmes et les lacunes soulevés rappellent que la spécification n’est encore qu’à l’état de brouillon

Quel est selon vous le futur de ce protocole ? Est-il capable de concurrencer HTTP ? L’implémentation vous semble t-elle simple ?

Mots-clé : HTML5httpprotocolewebwebsockets
Yohann Poiron

L’auteur Yohann Poiron

J’ai fondé le BlogNT en 2010. Autodidacte en matière de développement de sites en PHP, j’ai toujours poussé ma curiosité sur les sujets et les actualités du Web. Je suis actuellement engagé en tant qu’architecte interopérabilité.