---
title: WebSocket
source: https://synapx.fr/blog/websocket/
date: 2026-06-26
category: Développement
site: SynapxLab
---

# WebSocket

Les WebSockets sont une technologie de communication bidirectionnelle en temps réel qui permet d'établir une connexion continue entre un client (navigateur web, application mobile) et un serveur. Contrairement au modèle classique de communication HTTP, où le client doit envoyer une requête pour obtenir une réponse du serveur, les WebSockets permettent au serveur d'envoyer des données au client à tout moment, sans attendre une requête.

## Principe des WebSockets

Le fonctionnement des WebSockets repose sur les étapes suivantes :

- **Ouverture de la connexion :** Lorsqu'un client souhaite communiquer avec le serveur, il initie une connexion WebSocket. Cette connexion commence par une requête HTTP spéciale, appelée « handshake », qui passe ensuite à un protocole de communication WebSocket une fois établie.
- **Communication bidirectionnelle :** Une fois la connexion établie, les deux parties peuvent envoyer et recevoir des messages en temps réel. Contrairement aux requêtes HTTP classiques, il n'est pas nécessaire de rétablir la connexion pour chaque message, ce qui rend les WebSockets beaucoup plus performants pour les communications fréquentes.
- **Fermeture de la connexion :** Lorsque le client ou le serveur décide de terminer la communication, la connexion WebSocket est fermée proprement, libérant les ressources associées.

## Fonctionnalités possibles avec les WebSockets

Les WebSockets offrent un large éventail de possibilités pour des applications interactives et en temps réel.

- **Messagerie instantanée et chat en temps réel :** Les WebSockets sont parfaits pour les applications de chat où les messages doivent être transmis et affichés instantanément aux utilisateurs.
- **Notifications en temps réel :** Les notifications push peuvent être envoyées par le serveur aux utilisateurs pour les informer d'événements importants (mises à jour, alertes, nouveaux messages, etc.).
- **Jeux en ligne multijoueurs :** Les jeux nécessitant une synchronisation rapide entre les actions des joueurs peuvent utiliser les WebSockets pour une communication efficace en temps réel.
- **Tableaux de bord et monitoring :** Les WebSockets permettent d'afficher en direct les données d'un serveur, comme les métriques système ou les statistiques d'utilisation, avec des mises à jour en continu.
- **Collaborations en temps réel :** Pour les applications de collaboration comme les éditeurs de texte partagés ou les outils de dessin en ligne, les WebSockets facilitent la synchronisation des modifications entre plusieurs utilisateurs.
- **Streaming de données :** Les WebSockets sont idéaux pour les flux de données en temps réel, tels que les cours de la bourse, les résultats sportifs, ou les données de capteurs IoT.

### Avantages

- **Communication efficace :** Comme les connexions WebSocket restent ouvertes, il y a moins de surcharge par rapport aux requêtes HTTP répétées.
- **Réactivité :** Les messages peuvent être envoyés et reçus instantanément.
- **Économie de bande passante :** Les données sont envoyées dans un format JSON.

### Exemples

- **Un chat en direct sans utiliser de mécanismes comme Ajax.** (Surcharge des requêtes + latence)
- Notifications push.

### Streaming audio/vidéo avec WebSockets

Il est techniquement possible d'utiliser les WebSockets pour envoyer des flux, mais ce n'est pas optimisé. Les WebSockets n'offrent pas de mécanismes intégrés pour la compression ou l'encodage, d'où des temps de latence.

- **WebRTC :** solution la plus populaire pour le streaming audio et vidéo en temps réel. Il est conçu pour les communications peer-to-peer et offre une faible latence.
- **HTTP Live Streaming (HLS) :** protocole de streaming développé par Apple.
- **MPEG-DASH :** divise le contenu en segments et permet la diffusion adaptative.
- **RTMP (Real-Time Messaging Protocol) :** protocole traditionnellement utilisé pour le streaming en direct, notamment dans les plateformes de streaming comme YouTube ou Twitch.

## Mise en œuvre : les composants

Les trois composants d'une implémentation WebSocket standard :

### APACHE

Un seul domaine peut héberger plusieurs points de terminaison WebSocket distincts, par exemple un par salon de discussion, chacun étant associé à un port local différent.

Les échanges sont chiffrés via `wss` (WebSocket Secure, TLS), ce qui garantit la confidentialité des messages en transit.

Apache agit ici en **proxy inverse** : il reçoit les connexions WebSocket sur le port 443 et les route vers le processus PHP qui écoute en local. Le site HTTP/HTML n'est pas modifié ; seule la couche proxy est ajoutée.

### PHP

Pour le serveur, on s'appuie sur la **bibliothèque** Ratchet, dont le rôle est de gérer les connexions et les messages en temps réel.

Notre serveur reçoit un paquet de données JSON envoyé par un utilisateur, puis le redistribue à tous les autres utilisateurs connectés. Ce JSON contient non seulement les messages des utilisateurs, mais aussi des données techniques comme des identifiants, des informations sur le canal de discussion, etc.

Le fichier PHP `chat1.php` n'est pas servi par le web : il s'exécute en ligne de commande, directement depuis le terminal ou via une tâche planifiée (cron).

### JS + HTML

Le code JavaScript présenté implémente un client WebSocket qui permet à l'utilisateur de se connecter à un serveur de chat en temps réel, d'envoyer et de recevoir des messages.

Le script JavaScript agit comme un client de chat en ligne. Il se connecte à un serveur WebSocket (via une URL sécurisée `wss://`), envoie des données et reçoit des messages en temps réel. Les WebSockets permettent une communication bidirectionnelle et continue entre le client et le serveur, ce qui signifie que le serveur peut envoyer des messages au client sans que celui-ci ait besoin d'envoyer une requête d'abord.

### APACHE VirtualHost

Avant tout, on active les modules Apache nécessaires au proxy WebSocket. Sans `proxy_wstunnel`, le tunnel `ws://` ne sera pas établi :

```bash
sudo a2enmod proxy proxy_http proxy_wstunnel ssl
sudo systemctl restart apache2
```

```apache
<VirtualHost *:80>
    ServerAdmin moi@mon_orange.fr
    ServerName monsupersite.fr
    ServerAlias www.monsupersite.fr
    Redirect permanent / https://monsupersite.fr/
    DocumentRoot /var/www/vhosts/monsupersite.fr/public
</VirtualHost>

<IfModule mod_ssl.c>
    <VirtualHost *:443>
        ServerName              monsupersite.fr
        ServerAlias             www.monsupersite.fr
        DocumentRoot            /var/www/vhosts/monsupersite.fr/public

        # Proxy WebSocket (nécessite le module proxy_wstunnel, voir ci-dessous)
        ProxyRequests Off

        ProxyPass "/chat1" "ws://localhost:8443/"
        ProxyPassReverse "/chat1" "ws://localhost:8443/"

        ProxyPass "/chat2" "ws://localhost:8453/"
        ProxyPassReverse "/chat2" "ws://localhost:8453/"

        ProxyPass "/chat3" "ws://localhost:8463/"
        ProxyPassReverse "/chat3" "ws://localhost:8463/"

        # Configuration du répertoire
        <Directory "/var/www/vhosts/monsupersite.fr">
            Options -Indexes +FollowSymLinks +ExecCGI
            AllowOverride All
            Require all granted
        </Directory>

        # Configuration SSL
        SSLEngine on
        SSLCertificateFile      /etc/letsencrypt/live/monsupersite.fr/fullchain.pem
        SSLCertificateKeyFile   /etc/letsencrypt/live/monsupersite.fr/privkey.pem

        # SSL : désactiver les protocoles obsolètes et sécuriser les suites de chiffrement
        SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
        SSLCipherSuite HIGH:!aNULL:!MD5:!3DES
        SSLHonorCipherOrder on
        SSLCompression off
        SSLOptions +StrictRequire

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

    </VirtualHost>
</IfModule>
```

### PHP : chat1.php

Pour démarrer le fichier, on se place dans le répertoire où il se trouve. Le script `chat1.php` est conçu pour fonctionner en continu. Une fois lancé depuis la console avec la commande :

```bash
php chat1.php
```

le script restera en cours d'exécution tant que la console ou le serveur est en marche. Il agit comme un serveur en arrière-plan, écoutant les connexions WebSocket et traitant les messages en temps réel. Le script ne s'arrête pas automatiquement, il doit donc être arrêté manuellement ou redémarré en cas de besoin.

Si le script est lancé automatiquement via une tâche cron, il ne sera pas aussi simple de l'arrêter que `Ctrl + C`. Vous devez d'abord trouver l'ID du processus (PID) :

```bash
ps aux | grep chat1.php
kill PID
# en dernier recours seulement :
kill -9 PID
```

Utiliser un fichier de verrouillage (lock file) : l'idée est d'ajouter à votre script une vérification d'un fichier de verrouillage pour savoir s'il doit continuer à s'exécuter ou s'arrêter. Par exemple, le script pourrait vérifier l'existence d'un fichier comme `/tmp/chat1.lock`, et s'il est supprimé, le script s'arrêterait.

```bash
rm /tmp/chat1.lock
# via cron pour arrêter le script :
* * * * * pkill -f chat1.php
```

Ressources :

```bash
http://socketo.me/
https://packagist.org/packages/cboden/ratchet
composer require cboden/ratchet
```

`websocket.php` :

```php
<?php
require dirname( __FILE__ ) . '/vendor/autoload.php';
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

class MySocket implements MessageComponentInterface {
    protected $sockets;

    public function __construct() {
        $this->sockets = new \SplObjectStorage;
        date_default_timezone_set('Europe/Paris');
    }

    public function onOpen(ConnectionInterface $conn) {
        $this->sockets->attach($conn);
        error_log("Connection opened: {$conn->resourceId}");
    }

    public function onMessage(ConnectionInterface $conn, $msg) {
        $decodedMsg = json_decode($msg, true);
        if ($decodedMsg === null) {
            error_log("Invalid JSON message received from {$conn->resourceId}");
            return;
        }

        foreach ($this->sockets as $client) {
            if ($client !== $conn) { // Éviter d'envoyer le message à l'expéditeur
                $client->send(json_encode($decodedMsg));
            }
        }
        error_log("Message from {$conn->resourceId}: " . json_encode($decodedMsg));
    }

    public function onClose(ConnectionInterface $conn) {
        $this->sockets->detach($conn);
        error_log("Connection closed: {$conn->resourceId}");
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        error_log("An error occurred with connection {$conn->resourceId}: {$e->getMessage()}");
        $conn->close();
    }

    public static function startServer() {
        error_log("Starting WebSocket server...");
        $server = IoServer::factory(
            new HttpServer(
                new WsServer(
                    new MySocket()
                )
            ),
            8443
        );
        $server->run();
    }
}
MySocket::startServer();
```

### JS & HTML

`chat.js` :

```js
const MySocket = (function(){
  "use strict";
  let socket = null;
  let msg = {
    header: {
      host: window.location.host,
      pathname: window.location.pathname,
      user: 'nomuser'
    },
    chat: {
      channel: "all",
      message: null
    }
  };
  const init = () => {
    try {
      socket = new WebSocket(`wss://monsupersite.fr/chat1?token=${conf.session.compte}`);
      if (socket) {
        socket.onopen = (e) => {
          msg.object = 'onopen';
          socket.send(JSON.stringify(msg));
          socket.onmessage = (e) => {
            const result = JSON.parse(e.data);
            console.log(result)
          }
        };
      }
      socket.addEventListener("error", (event) => {
        event.preventDefault();
      });
    } catch (error) {

    }
  }
  const sendChat = (message) => {
    msg.chat.message = message;
    socket.send(JSON.stringify(msg));
  }

  return {
    init: init,
  };
})();

document.addEventListener('DOMContentLoaded', () => MySocket.init());
```
