Server push
Problème : AJAX est unidirectionnel
- Le client envoie des données dans la requête,
- Le serveur répond avec des données.
- Le serveur ne peut pas initier un transfert de données ;
- Le serveur ne peut pas appeler des fonctions (déclencher des évènements) chez le client.
Simuler une communication bidirectionnelle (Comet)
- Short polling, Long polling, Streaming.
Vraie communication bidirectionnelle
EventSource
, WebSockets.
Polling
Utile pour : notifications, compatibilité avec vieux navigateurs
Short polling
- Le client envoie une requête AJAX à intervalles réguliers (de l’ordre de la seconde),
- S’il y a des notifications depuis la dernière requête, le server les envoie dans la réponse.
Long polling, Streaming
- Le client ouvre une connexion HTTP avec le serveur,
- Le serveur envoie les entêtes mais ne ferme pas la connexion,
- Lorsque des notifications arrivent, le serveur les envoie dans la connexion ;
- (long polling) Le server ferme la connexion.
Polling
Avantages
- Compatible avec les vieux navigateurs,
- Ne demande pas de support spécifique chez le serveur.
Désavantages
- Gourmand en bande passante et ressources (overhead du protocole HTTP),
- Latence.
Event stream
Format de streaming unidirectionnel Serveur → Client : la connexion reste ouverte
HTTP/1.1 200 OK
Content-Type: text/event-stream
...
data: un message
data: un autre
data: message
event: toto
data: un message avec un nom
data: { "msg" : ["Porquoi", "pas", "du", "JSON"] }
- Un message d’une ligne,
- Un message sur plusieurs lignes,
- Un message nommé,
- On est libres de choisir le format des données.
Plus de détails : https://hpbn.co/server-sent-events-sse/.
Exemple de event stream : serveur
app.get('/api/notifications', function(req, res) {
res.set({ // Configuration des entêtes
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
}); // On envoie les entêtes
res.writeHead(200);
var count = 0; // On envoie un message
var timer = setInterval(function() { // toutes les 2 secondes
res.write('data: Hello ' + count + '\n\n');
count++;
if (count >= 10) { // Après 10 messages on
res.end(); // ferme la connexion
clearInterval(timer);
}
}, 2000);
});
- Facile en Node.js, plusieurs
paquets disponibles
(notamment,
sse-writer
). - Nécessite configuration spécifique pour Apache+PHP.
Exemple EventSource
: client
Le client est notifié des messages du server par des évènements
var evt = new EventSource("/api/notifications");
// Messages sans nom
evt.addEventListener('message', function(e) {
console.log(e.data);
});
// Messages nommés
evt.addEventListener('toto', function(e) {
console.log('Évènement nommé :', e.data);
});
- Pour : Léger, simple, relativement bien supporté,
- Contre : Unidirectionnel, nécessite le support du serveur,
- Démo : http://www.w3schools.com/html/tryit.asp?filename=tryhtml5_sse.
Web Sockets
Protocole de communication full-duplex, compatible avec HTTP.
- Protocole applicatif au dessus de TCP : pas de overhead HTTP ;
- Conçu pour utiliser le même port que HTTP (port 80 par défaut).
GET /app/socket HTTP/1.1
Upgrade: websocket
Connection: Upgrade
...
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
...
- Le client demande une connexion web socket,
- Le serveur répond avec
101 Switching Protocols
, - Le serveur et le client établissent une connexion TCP de type Web Socket
(schema
ws://
ouwss://
).
Exemple WebSocket : serveur
Exemple avec le paquet Node ws
:
var WebSocket = require('ws');
var server = new WebSocket.Server({ port: 8080 });
server.on('connection', function connection(ws) {
ws.on('message', function(message) {
console.log('received:', message);
});
ws.send('something');
});
Exemple WebSocket : client (navigateur)
Exemple avec l’API standardisée par le W3C:
var ws = new WebSocket('ws://localhost:8080');
ws.addEventListener('open', function(e) {
ws.addEventListener('message', function(e) {
console.log('received:', e.data);
});
ws.send('something else');
});
Web Sockets
Avantages
- Bidirectionnels,
- Peu de overhead,
- Standardisés par l’IETF en 2011 (et Candidate Recommendation du W3C),
- Disponibles dans tous les navigateurs modernes.
Désavantages
- Nécessitent de support dans le serveur,
- Difficiles à configurer avec Apache+PHP.
Bibliothèques
- Paquets Node.js :
ws
,μws
,engine.io
,primus
, … - Bibliothèque compatible Node.js : http://socket.io/;
- PHP : http://socketo.me/.