Fork me on GitHub

Communication bidirectionnelle Server push et websockets

Server push

Problème : AJAX est unidirectionnel

  1. Le client envoie des données dans la requête,
  2. Le server répond avec des données.
  • Le server ne peut pas initier un transfert de données ;
  • Le server 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 browsers

Short polling

  1. Le client envoie une requête AJAX à intervalles réguliers (de l’ordre de la seconde),
  2. S’il y a des notifications depuis la dernière requête, le server les envoie dans la réponse.

Long polling, Streaming

  1. Le client ouvre une connexion HTTP avec le server,
  2. Le server envoie les entêtes mais ne ferme pas la connexion,
  3. Lorsque des notifications arrivent, le server les envoie dans la connexion ;
  4. (long polling) Le server ferme la connexion.

Polling

Avantages

  • Compatible avec les vieux browsers,
  • Ne demande pas de support spécifique chez le server.

Désavantages

  • Gourmand en bande passante et ressources (overhead du protocole HTTP),
  • Latence.

Event stream

Format de streaming unidirectionnel Server → 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"] }
  1. Un message d’une ligne,
  2. Un message sur plusieurs lignes,
  3. Un message nommé,
  4. On est libres de choisir le format des données.

Exemple de event stream : seveur

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 envoye 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,
  • 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);
});

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
...
  1. Le client demande une connexion web socket,
  2. Le server répond avec 101 Switching Protocols,
  3. Le server et le client établissent une connexion TCP de type Web (schema ws://) Socket.

Web Sockets

Avantages

  • Bidirectionnels,
  • Peu de overhead,
  • Standardisés par l’IETF en 2011.

Désavantages

  • Nécessitent de support dans le server,
  • Pas adaptés au modèle d’exécution Apache+PHP,
  • API pas encore standardisée par le W3C.

Bibliothèques

Lectures