Partage
  • Partager sur Facebook
  • Partager sur Twitter

WebSocket avec un hébergement mutualisé

Sujet résolu
9 mai 2022 à 6:21:00

Bonjour,

J'aimerais mettre en place un projet fonctionnant en temps réel sur mon hébergement mutualisé. Le problème c'est que je ne sais pas du tout comment m'y prendre, de base je voulais partir sur du WebSocket mais j'ai peur que cela soit trop compliqué a cause de l'hébergement mutualisé. :euh:

Mon objectif serait de pouvoir au minimum envoyer des messages du serveur vers un client précis, et dans le meilleur des cas pouvoir aussi envoyer des messages depuis un client vers le serveur (ce qui me semble compliqué).

J'utilise Hostinger comme hébergeur et voici ce qu'ils disent à propos de WebSocket.

Comment pourrai-je faire du temps réel dans ces conditions ? Merci d'avance

  • Partager sur Facebook
  • Partager sur Twitter
9 mai 2022 à 6:43:30

Bonjour,

Il y a d'autres solutions que les websockets.

Pour diffuser du serveur vers un client, il y a le protocole SSE Server Sent Event très simple à mettre en oeuvre : https://developer.mozilla.org/fr/docs/Web/API/Server-sent_events/Using_server-sent_events

Il est possible aussi d'utiliser le protocole Mercure : https://github.com/dunglas/mercure

Pour ma part, j'utilise Mercure pour notifier des infos de type domotique et j'ai réalisé un chat avec aussi.

A+

-
Edité par monkey3d 9 mai 2022 à 6:43:58

  • Partager sur Facebook
  • Partager sur Twitter
9 mai 2022 à 8:50:21

D'accord merci je vais me renseigner sur tout ça, et du coup pour les envois client vers serveur j'imagine que tu utilises AJAX ? ou autre chose ?

EDIT:

J'ai test SSE, du coup c'est bien mais enfaite je ne contrôle pas l'envoi des données, ce qui est un réel problème dans mon cas.

Le listener reçoit des données constamment, le seul moyen est de le close() pour arrêter la réception de données (à cause de la reconnexion automatique).

J'aimerais qu'ils reçoivent les données seulement quand je call le fichier PHP.

Mon code :

<?php
    header("Cache-Control: no-cache");
    header("Content-Type: text/event-stream");

    echo 'data: Message envoyé à' . date(DATE_ISO8601) . "\n\n";

    ob_end_flush();
    flush();
?>
    const evtSource = new EventSource("assets/php/sse.php");
    evtSource.onmessage = function(event) {
        console.log(event);
        console.log(event.data);
        evtSource.close();
    };

Concernant mercure, je me suis renseigné et j'ai honnêtement du mal à comprendre comment ça fonctionne, apparemment il faut installer un logiciel sur le serveur ?

EDIT 2:

J'ai réussi à faire tourner quelque chose, qui donne ce que je souhaite.

    header("Cache-Control: no-cache");
    header("Content-Type: text/event-stream");
    session_start();

    $data = @$_SESSION['tmpData'];

    if (isset($_POST['token']) && $_POST['token'] == $_SESSION['token']){
        $_SESSION['tmpData'] .= $_POST['data'];
    }
    if ($data != null) {
        echo 'data: Message envoyé à ' . $data . "\n\n";
        $data = null;
        unset($_SESSION['tmpData']);
    }
    
    ob_end_flush();
    flush();

Le client1 ne reçoit rien et passe son temps à se reconnecter. Un second client2 peut faire un call AJAX au fichier PHP. Ce call ajoutera les données à la SESSION, et lors de la prochaine connexion du client1 le fichier PHP enverra les données. Et c'est une boucle infinie.

Je ne sais pas si c'est très propre, existerait-il une meilleure alternative ?

-
Edité par Kévin_ 9 mai 2022 à 11:22:22

  • Partager sur Facebook
  • Partager sur Twitter
10 mai 2022 à 7:08:23

Je ne comprends pas bien ton problème avec le SSE.

SSE est un protocole qui pousse (push) des infos du serveur vers le(s) client(s). Le contrôle de ce que tu envoies doit donc être faite côté serveur.

Non, les clients ne se passent pas leur temps à se connecter ... le canal de com est établi entre le client et le serveur quand la partie javascript est lancée. Et ensuite via ce canal établi, le serveur l'utilise pour pousser vers le(s) client(s) les informations ... si il y a des infos à transmettre. Si tu fais un close dans le handler alors ton canal est fermé et tu dois en ouvrir un nouveau : dans ce cas, l'usage de SSE est inutile.

Donc tu envoies des données au serveur et le SSE va aller voir régulièrement (tu peux paramétrer le "régulièrement") si des données nouvelles sont présentes et si c'est le cas les pousser vers les clients. Côté client tu récupères les données et tu les affiches suivant ton besoin. 

Quelques points par rapport à ton code : ne pas masquer les erreurs par un @, retourne les données plutôt au format json, le ob_end_flush me semble inutile.

Oui il faut installer le logiciel Mercure pour l'utiliser : https://mercure.rocks/docs/hub/install

Peut-être as tu lu cet exemple pour SSE : https://www.w3schools.com/html/html5_serversentevents.asp

Je ne pourrai plus continuer cette discussion jusqu'au 15 mai ...

A+

-
Edité par monkey3d 10 mai 2022 à 7:10:26

  • Partager sur Facebook
  • Partager sur Twitter
10 mai 2022 à 17:01:30

J'avais, en effet, vu un exemple mais pas celui-là.

J'ai essayé sans le "ob_end_flush()" et pas de différence.

Le "@" était temporaire le but était juste d'avoir un code qui corresponde à mes attentes, avant de faire un code propre.

Cependant même avec le code de l'exemple de W3, je continue à recevoir des messages en boucles.

    header("Content-Type: text/event-stream");
    header("Cache-Control: no-cache");

    $time = date('r');
    echo "data: The server time is: {$time}\n\n";
    flush();
    const evtSource = new EventSource("assets/php/sse.php");
    evtSource.onmessage = function(event) {
        console.log(event);
        console.log(event.data);
    };

Et d'après ce que j'ai compris de SSE, c'est lié au fait qu'il considère un fichier PHP finit d'être exécuté comme une déconnexion, et donc il se reconnecte automatiquement au bout de quelques secondes (créant ainsi la boucle). Après j'ai peut-être mal compris.

  • Partager sur Facebook
  • Partager sur Twitter
15 mai 2022 à 7:51:04

Je reviens !

Mais tout fonctionne bien : tu as un push de data toutes les 3 secondes - je ne vois pas pourquoi tu veux couper la connexion.

Non il ne se reconnecte pas : voir mes explications ci-dessus.

Non, ce n'est pas une boucle au sens classique c'est un push de data sur un canal déjà ouvert.

Pour rappel aussi tu peux changer le time du SSE.

A+

  • Partager sur Facebook
  • Partager sur Twitter
17 mai 2022 à 21:07:58

Justement je ne souhaite pas un push toutes les 3 secondes. Je souhaite push seulement quand "je le décide", seulement quand le fichier PHP est update par un call AJAX d'un autre client par exemple.
  • Partager sur Facebook
  • Partager sur Twitter
18 mai 2022 à 7:21:23

Dans ce cas, il te suffit de retourner une réponse null quand il n'y a rien à mettre à jour et le tour est joué.

C'est donc au niveau du code de ton serveur qu'il faut le faire.

A+

  • Partager sur Facebook
  • Partager sur Twitter
18 mai 2022 à 19:22:36

Kévin_ a écrit:

EDIT 2:

J'ai réussi à faire tourner quelque chose, qui donne ce que je souhaite.

    header("Cache-Control: no-cache");
    header("Content-Type: text/event-stream");
    session_start();

    $data = @$_SESSION['tmpData'];

    if (isset($_POST['token']) && $_POST['token'] == $_SESSION['token']){
        $_SESSION['tmpData'] .= $_POST['data'];
    }
    if ($data != null) {
        echo 'data: Message envoyé à ' . $data . "\n\n";
        $data = null;
        unset($_SESSION['tmpData']);
    }
    
    ob_end_flush();
    flush();

Le client1 ne reçoit rien et passe son temps à se reconnecter. Un second client2 peut faire un call AJAX au fichier PHP. Ce call ajoutera les données à la SESSION, et lors de la prochaine connexion du client1 le fichier PHP enverra les données. Et c'est une boucle infinie.

Je ne sais pas si c'est très propre, existerait-il une meilleure alternative ?

-
Edité par Kévin_ 9 mai 2022 à 11:22:22


Dans ce cas ça reviens à faire ce que j'ai fait ici ?

-
Edité par Kévin_ 18 mai 2022 à 19:22:53

  • Partager sur Facebook
  • Partager sur Twitter
18 mai 2022 à 21:13:37

Oui cela me semble bien.

Sujet résolu je crois.

Bye

  • Partager sur Facebook
  • Partager sur Twitter
19 mai 2022 à 13:36:31

Merci de ton aide, je vais me baser la-dessus.
  • Partager sur Facebook
  • Partager sur Twitter