Le protocole WebSocket vise à développer un canal de communication full-duplex sur un socket TCP.
LOL. C’est clair non ?
Vous inquiétez pas, tonton Sam est là.
Le Web a évolué. On est passé de Gopher a HTTP 1 puis 1.1. Et on a eu AJAX pour rafraîchir la page sans tout recharger.
Et maintenant on a des apps complètes qui font des centaines de requêtes au serveur alors même que l’utilisateur ne change pas de page. D’ailleurs, je parie que plein de gens ne savent même plus ce qu’est une page…
Le problème c’est qu’AJAX, c’est toujours HTTP, et HTTP est sans état (stateless) : il ne garde aucune information en mémoire d’une requête à l’autre. Ça a des avantages, mais cela implique qu’à chaque requête, il faut ouvrir une connexion et la refermer. Ce qui bouffe quelques ms à chaque fois, et d’autant plus si on utilise SSL.
Une autre limite, c’est que le serveur ne peut pas envoyer de données au client (ici le navigateur) si le client ne fait pas une requête au préalable. Du coup, pour savoir si il y a quelque chose de nouveau, le navigateur doit régulièrement faire des requêtes au serveur ou utiliser des gros hacks comme le long polling.
Les websockets (c’est un abus de langage, on devrait parler du protocole Websocket) ont été créés pour répondre à ces besoins : elles permettent d’ouvrir une connexion permanente entre le navigateur et le serveur. Ainsi, chaque requête est plus rapide, et plus légère. En prime, le serveur peut envoyer des requêtes au navigateur pour le prévenir qu’il y a du nouveau.
Ceci permet de faire tout ce que permettait de faire AJAX mais en plus rapide, et en plus léger. Et également d’envoyer des notifications (ce contenu a changé, un message est arrivé, l’autre joueur a fait cette action…) au navigateur au moment où l’événement se produit.
En gros, de faire des apps Web quasi temps réel.
Il existe d’autre technos pour faire cela : applets Java, flash, comet, server sent events…
Mais aucune n’ont décollé. Websocket est donc aujourd’hui la solution de facto.
Caractéristiques
Le protocole Websocket utilise l’abréviation ws
et wss
si SSL, les URLs vers des endpoints websocket ressemblent donc à : ws://domaine.tld/chemin/vers/truc/
.
Intelligemment, il utilise un handshake compatible avec celui de HTTP, permettant à un serveur de gérer les deux sur les mêmes ports. Donc on peut faire du Websocket sur le port 80 et 443. Néanmoins, certains proxy se gourent quand ils voient du websocket non chiffré et gauffrent votre connexion en la traitant comme du HTTP. Donc si vous voulez une app solide, investissez dans un certif SSL.
Tout ça fonctionne à partir de IE10. Notez comme IE est devenu le standard de ce qui ce fait de moins bien à tel point que je n’ai même pas besoin de vous parler des autres, vous savez que ça marche. Il existe en plus des plugins flash pour simuler des websockets sur les navigateurs anciens, c’est à dire les encore plus vieux IE.
Par défaut, les websockets permettent de faire de requêtes crossdomain, contrairement à AJAX. Avec les nouvelles apps qui utilisent NodeJS en local (comme popcorntime) on peut imaginer une nouvelle type d’attaque : une page web qui se connecte à un serveur websocket local de votre machine. Comme les websockets sont souvent utilisées pour du RPC, il y a du potentiel.
Bon, ta gueule, et montre le code
Vous noterez que ce qui prend du temps dans l’exemple c’est la connexion, qu’on ne fait qu’une fois. Ensuite l’échange de données est super rapide.
Ceci est un exemple Javascript, mais un client websocket n’est pas forcément un navigateur. En fait, c’est très précisément le cas avec WAMP, dont les clients peuvent être des programmes Python, Objective C, Java, C++, etc. L’avantage de WAMP, c’est qu’il automatise toute la machinerie pour découper la logique de son programme en divers fonctions et services, plutôt que d’avoir à tout faire à la main avec send()
et onmessage()
.
Dans tous les cas, il vous faudra un serveur qui supporte les Websockets pour l’utiliser. En Python, c’est Tornado ou Twisted (sur lequel est basé le serveur WAMP crossbar). En Javascript, c’est NodeJS. Quoi qu’il en soit, il vous faut un logiciel qui gère l’IO de manière non bloquante, car il y a de nombreuses connexions ouvertes en simultanées, si on veut que ça soit performant.
C’est assez marrant car je m étais justement posé la question à juste titre quand tu parlais de WAMP. Je suis repassé par mes cours réseaux. merci d’éclaircir une peu plus ma lanterne.
sinon un petit article se dictionnary lookup serait cool surtout pour dire “eh les gars on a notre switch” :)
Les fondamentaux en Python sont pas trop ma couverts ailleurs, donc généralement on fait plutôt des articles sur des notions moins claires. Peut être qu’un jour de ferait des tutos pour apprendre Python, mais c’est pas pour tout de suite.
Sinon petite coquillev
En prime, la serveur => en prime le serveur
Techos=> technos (sauf si tu voulais parler de tacos)
Cheer :)
En Python, pour faire du WebSockets en AsyncIO, il y a aussi aiohttp.
Une API high-level est en cours d’écriture pour aiohttp.web.
Un grand merci.
J’entends parler de ça depuis des années, j’ai jamais compris ce que c’était.
Haha, les flocons de neige en scred :)
Désolé…
Correction technique: HTTP 1.0 oui, il faut rouvrir la connection à chaque requete. HTTP 1.1 a introduit le header keep-alive qui permet justement de pas avoir à faire le handshake à chaque fois. C’est mis par défaut par 99% des lib/framework/servers. Rien à voir avec l’état stateless de http à ce niveau. Les browsers ont d’ailleurs des pools de connections (6 souvent) qu’ils ouvrent pour chaque origines.
Le principal problème de HTTP 1.x c’est surtout que c’est unidirectionel, donc ça marche pas pour les notifications (sauf tricherie genre long polling). C’est le principal cas d’utilisation des websockets d’ailleurs.
Ouai, je simplifies toujours. On peut aussi noter que HTTP renvoi tout de même tous les headers (dont les cookies) et s’attend à une réponse d’un code status, à chaque fois. De plus, keep alive possède forcément un timeout (par défaut 60 sec, c’est court), ce qui a forcé l’éclosion de ce genre de hacks (https://github.com/ocombe/jQuery-keepAlive). Bref, HTTP a été bricolé pour maintenir la connexion, mais n’a pas du tout été pensé pour ça à l’a base.
Je viens de faire un test hier d’ailleurs, 100 requêtes AJAX en local c’est toujours plus lent que 1000 RPC avec WAMP.