php socket

MoutMout
Invité n'ayant pas de compte PHPfrance

21 oct. 2015, 06:56

Bonjour à tous,

Alors voilà je suis sur un projet :-* , celui-ci contiendra un tchat sur la page d'accueil.
Aprés pas mal d'essaye j'ai trouvé que le meilleur compromis pour MOI était les sockets.

Le problème que je rencontre aujourd'hui est qu'à chaque fois que je vais sur une autre page que l'accueil et que je reviens sur l'accueil, l'historique du tchat est vierge...
Ducoup on ne peut pas voir les messages postés il y a à peine 30 secondes si on était pas sur la page d'accueil juste avant ...

Je demande de l'aide car je suis perdu et la documentation sur les sockets est très limite je trouve ...

Mon code est en deux parties, le serveur : websocket_serveur.php et le client : script.js

websocket_serveur.php
#!/usr/bin/php -q
 <?php

  /* Cette source est une reprise avec un profond remaniement du tutoriel de
     http://sii-rennes.developpez.com/articles/un-chat-en-html5-avec-les-websockets/
     qui n’est absolument pas fonctionnel en l’état actuel (<2015-06-28). C’est un bon départ
     pour “tâter” voir ce que sont les websockets avec un serveur PHP. La source d’information
     la plus sérieuse, mais qui n’est toujours pas “normative” est la fastidieuse mais abordable
     http://tools.ietf.org/html/rfc6455 que je vous invite à parcourir (en anglais).
     NOTE je suis convaincu que c’est au serveur (cette source) de traiter le cas de message de
          plus de 125 caractères, ce qui n’est pas le cas (bon, pour un chat, tronquer coté
          client).
     TODO le document rfc6455 décrit de nombreux cas où la connexion doit être close (paquet
          “non conforme”)
     J’ai essayé avec Chrome et Firefox, Vous constaterez que Firefox est prompt au tennis de
     table. Je crois que le sujet doit-être repensé et ré-écrit pour un chat plus sérieux. Il
     y a des choses inutilisées ici, comme l’affectation d’un uniqid à un utilisateur. Tout se
     confond: utilisateur, pseudo, socket, uniqid…

     Ce script est "normalement" lancé depuis une console sur le cerveur. Il est possible de le
     lancer depuis un fureteur, mais que si on peut rendre l'exécution "sans fin", ce que votre
     hébergeur interdit sûrement.

     Précision sur cette source:
     - comme ce script est sensé être lancé depuis une console, j’utilise la couleur pour
       “dynamiser” les messages de débogage, (c’est sympa et si vous regardez un peu, ça mange
       pas beaucoup de pain !)

     Pour la mise en forme:
     - je “joue” des ressources de coloration de mon éditeur afin de “grouper” visuellement le
       code
     - Jamais de code sur la première colonne (sauf #) : strictement réservé au débogage
     - Le “principal” du code en bas de source, les fonctions et autres définitions en haut, le
       la plus “légère” à la plus “lourde”
    - indentation de 1 espaces en JS, deux en PHP
    - j’évite de dépasser 96 colonnes par ligne (fini l’écran 12 lignes x 40 colonnes)
      */
  error_reporting(E_ALL);

  define ("_cLiR_", "\x1B[0J");
  define ("ConClr", "\x1Bc"); // Effacement de l'écran

  define ("_N", "\x1B[1;30m"); // Noir
  define ("_R", "\x1B[1;31m"); // Rouge
  define ("_V", "\x1B[1;32m"); // Vert
  define ("_J", "\x1B[1;33m"); // Jaune
  define ("_B", "\x1B[1;34m"); // Bleu
  define ("_M", "\x1B[1;35m"); // Magenta
  define ("_C", "\x1B[1;36m"); // Cyan
  define ("_G", "\x1B[1;37m"); // Gris (heu… blanc)
  define ("C_", "\x1B[0;0m");  // fin de coloration

  define("HOST", "IP.LOCAL.DU.SERVEUR"); // host
  define("PORT",  PORT-CHOISI);         // port

  function say ($msg="") { print($msg."\n"); } // Causerie "normale"
function   cons ($l, $m="") { if (@$GLOBALS['debug']) print(_G.$l.": "._R.$m.C_."\n"); }

  class User {
  /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
    public $id;
    public $socket;
    public $handshake;

    public function __construct ($socket) {
      $this->id=uniqid();     // Ici, le client est unique !
      $this->socket=$socket;  // La socket pour lui
      $this->handshake=false; // Jamais "upgradée" (ou "handchecké")
    }
  }

  function SocketCreate ($address, $port){
  /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
    $master=socket_create(AF_INET, SOCK_STREAM, SOL_TCP)     or die("socket_create() failed");
    socket_set_option($master, SOL_SOCKET, SO_REUSEADDR, 1)  or die("socket_option() failed");
    socket_bind($master, $address, $port)                    or die("socket_bind() failed");
    socket_listen($master, 1024)                               or die("socket_listen() failed");
    print("Server Started : ".date('Y-m-d H:i:s')."\n");
    print("Master socket  : ".$master."\n");
    print("Listening on   : ".$address." port ".$port."\n\n");
    return $master;
  }

    function ConnecteClient ($socket) { // Créer un client. "socket" est sa socket
    /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
    global $sockStk, $usrStk;

      $user=new User($socket);           // $this-> :id, socket, handshake
      array_push($usrStk,$user);         // On le place dans la liste des clients
      array_push($sockStk,$socket);      // Et sa socket dans la liste des sockets
cons(__LINE__, $socket." CONNECTED!");   // Information de dégugging
cons(__LINE__, print_r($usrStk, !0).""); // Information de dégugging
    }

  function GetUserBySocket ($socket) {
  /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
  global $usrStk;

cons(__LINE__, _J.print_r($socket, !0).""); // Information de dégugging
    $n=count($usrStk);                 // Nombre de connexion à cette socket
    for($i=0; $i<$n; $i++)             // Tous les utilisateur en revue
      if($usrStk[$i]->socket==$socket) // Celui-ci:
        return $usrStk[$i];            // Retourné le trouvé
    return null; // NOTE Le cas d'une réponse "null" n'est pas traité
  }

  function DeconnecteClient ($socket) { // Supprimer utilisateur utilisant cette socket
  /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
    global $sockStk, $usrStk;

    $n=count($usrStk);                       // Nombre de connexion à cette socket
    for($i=0; $i<$n; $i++)                   // Les utilisateur en revue
      if ($usrStk[$i]->socket==$socket)
        break;                               // $found <- $i : trouvé
    $i<$n && array_splice($usrStk, $i, 1);   // Trouvé : supprimé de la liste des utilisateurs
    $index=array_search($socket, $sockStk);  // Chercher la socket, maintenant
    socket_close($socket);                   // Fermer la connexion
cons(__LINE__, $socket." DISCONNECTED!"); // Debugging
    if($index>=0) array_splice($sockStk, $index, 1); // Supprimer de la liste si dedans
  }

  function Unmask ($text) { // "Dé-masquer" le "cadre" texte entrant
  /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
/*  1er octet: Drapeaux (ex: 0x81 -> Fin + Text

    2nd octet: (maskFlag<<7) + len du texte avec cas spécial pour len>125 et len>65535
    ..
    --- (3e, 5e ou 9e) masque 32 bits
    ex:

      89 [01..7D] mm mm mm mm tt......tt len caratères                (texte[0] en frame[6])
      Cas d'un texte "masqué" de lg < 126 car.

      81 [01..7D] tt.......tt len caratères                           (texte[0] en frame[2])
      Cas d'un texte de lg < 126 car.

      89 7E ll ll mm mm mm mm tt......tt                              (texte[0] en frame[8])
      Cas d'un texte "masqué" de lg > 126 et < 65535 car.

      81 7E ll ll tt......tt                                          (texte[0] en frame[4])
      Cas d'un texte de lg > 126 et < 65535 car.

      89 7F ll ll ll ll ll ll mm mm mm mm tt......tt                  (texte[0] en frame[12])
      Cas d'un texte "masqué" de lg > 65535 et < 281474976710655 car.

      81 7F ll ll ll ll ll ll tt......tt                              (texte[0] en frame[8])
      Cas d'un texte de lg > 126 et > 65535 et < 281474976710655 car.

      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-------+-+-------------+-------------------------------+
     |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
     |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
     |N|V|V|V|       |S|             |   (if payload len==126/127)   |
     | |1|2|3|       |K|             |                               |
     +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
     |     Extended payload length   |                               |
     |  cont., if payload len==127   |                               |
     + - - - - - - - - - - - - - - - +-------------------------------+
     |                               |Masking-key, if MASK set to 1  |
     +-------------------------------+-------------------------------+
     | Masking-key (continued)       |          Payload Data         |
     +-------------------------------- - - - - - - - - - - - - - - - +
     :                     Payload Data continued ...                :
     + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
     |                     Payload Data continued ...                |
     +---------------------------------------------------------------+

     NOTE Les trames TCP envoyées par les web-sockets (clients) sont toujours masquée) */

//cons(__LINE__, "masked: \""._C.bin2hex($text).C_."\".\n");
    $length=ord($text[1])&0x7F;          // Longeur du texte "utile"
    $mFlgP=(ord($text[1])&0x80) ? 4 : 0; // Indicateur de masquage
    $l=strlen($text);                    // Longueur de la trame TCP embarquée
    if($length==0x7E)                    // Texte composé de moins de 65536 caractères
     $pos=4;                             // Position du masque
    elseif($length==0x7F)                // Texte composé de plus de 65536 caractères
     $pos=8;                             // Position du masque
    else                                 // Texte composé de moins de 126 caractères
     $pos=2;                             // Position du masque
    if ($mFlgP)                          // Le texte est "masqué" (0 ou 4)
      for ($j=0, $i=$pos+4; $i<$l; ++$j, ++$i) // 4: lg. du masque
        $text[$i]=$text[$i]^$text[$pos+($j&3)];
//cons(__LINE__, "Unmask: \""._J.bin2hex($text).C_."\".\n");
//cons(__LINE__, "messag: \""._R.substr($text, $pos+$mFlgP, $l-$pos-$mFlgP).C_."\",\n");
    return(substr($text, $pos+$mFlgP, $l-$pos-$mFlgP));
  }

  function Mask ($text, $mask=0) { // Encode message for transfer to client. {
  /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
  // "$mask" est soit une chaîne de 4 caractères, soit 0
  // NOTE Les messages envoyés par le serveur à une web-socket ne doivent pas être masqués
//cons(__LINE__, _G.$text.C_.", longueur: "._M.strlen($text).C_.".\n");
//cons(__LINE__, "    "._M.bin2hex($text).C_.".\n");
    $l=strlen($text);         // Longueur du texte
    if ($mask)                // Réaliser le masquage
      for ($i=0; $i<$l; $i++)
        $text[$i]=$text[$i]^$mask[$i&3];
    $mskB=$mask ? 0x80 : 0;
    $entet=chr(0x80|($text=="PING" ? 0x9 : $text=="PONG" ? 0xA : 0x1)); // "Fin", "text"
    if ($l<0x7E)
      $entet.=chr($mskB|$l);
    elseif ($l<0xFFFF)
      $entet.=chr($mskB|0x7E).chr($l>>8).chr($l&0xFF);
    else
      $entet.=chr($mskB|0x7F).chr($l>>24).chr($l>>16).chr($l>>8).chr($l&0xFF);
    $entet.=$mask ? $mask[0].$mask[1].$mask[2].$mask[3] : "";
//cons(__LINE__, _M.bin2hex($entet.$text).C_.".\n");
    return $entet.$text;
  }

  function Handshaking ($user, $buffer) { // Utilisateur à "valider"
  /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
cons(__LINE__, "Requête \"Handshake\": reçu du client :"); // Debugging
cons(__LINE__, $buffer);
    if(preg_match("/GET (.*) HTTP/"   ,$buffer, $match)) $rsc=$match[1]; // ???
    if(preg_match("/Host: (.*)\r\n/"  ,$buffer, $match)) $hst=$match[1];
    $headers=array();
    $lines=preg_split("/\r\n/", $buffer);
    foreach($lines as $line) {
      $line=chop($line);
      if(preg_match('/\A(\S+): (.*)\z/', $line, $matches))
        $headers[$matches[1]]=$matches[2];
    }
    $secKey=$headers['Sec-WebSocket-Key'];
    $secAccept=base64_encode(sha1($secKey.'258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));

    $upgrade ="HTTP/1.1 101 Web Socket Protocol Handshake\r\n". // hand shaking header
    "Upgrade: websocket\r\n" .
    "Connection: Upgrade\r\n" .
    "WebSocket-Location: ws://$hst".$rsc."\r\n". // ???
    "Sec-WebSocket-Accept: $secAccept\r\n\r\n";
    socket_write($user->socket, $upgrade, strlen($upgrade));
    $user->handshake=true; // Fait, ouffff!
cons(__LINE__, "Réponse :");
cons(__LINE__, $upgrade); // Debugging
cons(__LINE__, "Requête exécutée."); // Debugging
  }

  function Emet ($client, $msg){
  /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
    say(__LINE__."> ".$msg);
    $msg=Mask($msg); // NOTE inutile !
    socket_write($client, $msg, strlen($msg));
  }

  function Process ($user, $msg) {
  /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
    global $sockStk, $usrStk;

  // $action=Unmask($msg); // cons(__LINE__, bin2hex($msg));
  $action=str_replace("\n", "\\n", Unmask($msg));
  say(_G.__LINE__." ← ".C_.$action);
  $arr=json_decode($action, !0);
cons(__LINE__, print_r($arr, !0));
  $name=$arr['usr'];
cons(__LINE__, "\$name: \"$name\"");
  if ($name) switch($name) {
   case "system": say("L'hôte dit: "._R.$arr['mes']._C);    break;
   case "syscli": say("Un client dit: "._G.$arr['mes'].C_); break;
   default      : $action=Mask($action);
                  $n=count($usrStk);     // Nombre de connexion à cette socket
                  for($i=0; $i<$n; $i++) // Tous les utilisateur en revue
                    socket_write($usrStk[$i]->socket, $action, strlen($action));
   }
   else switch ($action) {
   case "PING":
    $action=Mask("PONG");
    socket_write($user->socket, $action, strlen($action));
    break;
   default    : say(bin2hex($msg)." ????");
  }
}



  /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
  /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
  $debug=true;
cons(0, ConClr."\r");
  $master=SocketCreate(HOST, PORT); // Création de la socket
  $sockStk=array($master);       // En en fait une pile
  $usrStk=array();               // Liste des utilisateurs

  while(true) {
    $sSClone=$sockStk;                  // Cloner la référence : socket_select() modifie la pile
    $write=$except=NULL;                // Parce que &NULL n'est pas admis par socket_select()
    socket_select($sSClone,$write,$except,NULL); // Voir si un message en attente -> $sSClone
    foreach($sSClone as $socket) {      // Observation des connectés
      if($socket==$master) {            // Tiens! La connexion originale !
//cons(__LINE__, _B."\$socket==\$master");
        // NOTE Bloquera ici si aucune autre connexion n'existe
        $client=socket_accept($master); // $client sera une nouvelle ressource "socket"
        if($client<0) {                 // Une erreur est survenue
          say(__LINE__.": socket_accept() failed"); // Oups !
          continue;
        }
        else
          ConnecteClient($client);      // Connexion
      }
      else {                            // Une connexion déjà ouverte
//cons(__LINE__, _B."\$socket!=\$master");
        $bytes=@socket_recv($socket, $buffer, 2048, 0); // Disposé à recevoir
        if($bytes==0)                   // Si on n'a rien reçu maintenant :…
          DeconnecteClient($socket);    // …déconnexion de cette socket
        else {
          $user=GetUserBySocket($socket); // Retrouver l'utilisateur depuis sa socket
          if(!$user->handshake)         // Jamais valider…
            Handshaking($user, $buffer);// …valider.
          else
            Process($user, $buffer);    // Traiter le message reçu.
        }
      }
    }
  }
script.js
var d = new Date();
   var h = d.getHours(); 
   var m = d.getMinutes(); 
   if(h < 10 )
   {
   var heure = '0'+h+':'+m;
   }
   else if(m < 10)
   {
   var heure = h+':0'+m;
   }
   else if(m < 10 && h < 10)
   {
   var heure = '0'+h+':0'+m;
   }
   else
   {
   var heure = h+':'+m;
   }
   
   const kStTxt=["Ouvrant","Ouvert","Fermant","Fermé"]
   ,kStCol=["yellow","green","orange","red"]
   ;
   var ws
   ,colo="#969696"
   ,host="ws://IP.PUBLIQUE:PORT/"
   ;
    function colz (m, c){ /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
     return "<span style=color:"+c+">"+m+"</span>"
	 
    }
	function linkU (u){ /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
     return "<a id=connectusername href=accueil.php?page=profilamis&amis="+u+">"+u+"</a>"
	 
    }
    function $ (id) { /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
     return document.getElementById(id)
    }
    function usr (a) {  /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
     $("usr").innerHTML+=heure+" "+linkU(a.usr)+": "+colz(a.mes, a.col).replace(/\n/, "<br />")
	  element = document.getElementById('usr');
		element.scrollTop = element.scrollHeight;
    }
    function log (m){ /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
    // $("debug").innerHTML+="<br />"+m
    }
    function onkey(e){  /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
     if(e.keyCode==13)
      send();
    }
    function send(m){ /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
      var _u, _t=$("message"), _p=$("pseudo");
      if (_u=m===_u) {
       m=_t.value;
	   sedo = _p.value;
       if(!m) { alert("Il n'y a rien à envoyer !");return }
       _t.value="";
       _t.focus();
       }
      m="{\"usr\":\""+(_u ? sedo : "syscli")+"\""
       +",\"mes\":\""+m+"\n\""
       +",\"col\":\""+(_u ? colo : "red")+"\"}";
      try{ ws.send(m); log('Sent: '+m); } catch(ex){ log(ex); }
    }
  /// <s"*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*">
   function init () {
    try{
       ws=new WebSocket(host);
      
       ws.onmessage=
        function(m){
        var _a;
         eval("_a="+m.data);
         usr(_a);
        };

     }
     catch(ex){ log(ex); }
     setInterval(function () { // "CONNECTING","OPEN","CLOSING","CLOSED"
     }, 100)
   }
Cordialement MoutMout

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9783 Messages

21 oct. 2015, 09:22

Le problème que je rencontre aujourd'hui est qu'à chaque fois que je vais sur une autre page que l'accueil et que je reviens sur l'accueil, l'historique du tchat est vierge...
Ducoup on ne peut pas voir les messages postés il y a à peine 30 secondes si on était pas sur la page d'accueil juste avant ...

Je demande de l'aide car je suis perdu et la documentation sur les sockets est très limite je trouve ...
En l’occurrence, ce n'est pas un problème de socket mais de conception si j'ai bien compris ton soucis.

Le système de chat que tu as mis en place est éphémère, car tu ne stockes les messages envoyés nulle part.

2 possibilités :
1) soit tu veux réafficher les derniers messages qui ont été échangé avant que l'utilisateur n'arrive sur le site
2) soit tu veux réafficher lors d'un changement de page les précédents messages qui ont été reçus par l'utilisateur.

Dans le cas n°1, il faut que tu stockes tous les messages envoyés sur ton serveur dans une base de données ou des fichiers de log.
Dans le cas n°2, tu peux stocker ces infos directement dans le navigateur (avec la fonctionnalité local storage de html5 par exemple)


Mon conseil serait plutôt d'opter pour la solution 1 qui te permet de loguer les messages qui ont été envoyés ce qui est toujours utile si un jour il y a des débordements.
Par ailleurs, si un utilisateur A envoie un message à un utilisateur B, alors que ce dernier est en train de changer de page, la socket va être interrompue quelques secondes et il risque de ne jamais recevoir le message.
Quand tout le reste a échoué, lisez le mode d'emploi...

MoutMout
Invité n'ayant pas de compte PHPfrance

21 oct. 2015, 20:27

Salut,

Merci d'avoir pris le temps de me répondre. Oui je sais qu'il n'y a aucun enregistrement des messages reçus c'est d'ailleurs la mon problème. Je sais comment afficher un message des que l'utilisateur viens sur le chat avec [ ws.onopen ]
Mais je ne sais pas comment je peux effectuer le stockage log ou bdd des messages du chat avec mon script js....

Si tu pouvais me guider dans la démarche cela serait cool.

MoutMout
Invité n'ayant pas de compte PHPfrance

25 oct. 2015, 07:18

Plz help ! :cry:
Je sais qu'il faut que je "stocke" les messages du chat quelque part,
mais via JavaScript... à par "localstorage" pour stocker...
Je ne trouve pas comment écrire dans une BBD ou dans un fichier qui pourrais contenir l'historique du chat
(vu que JS c'est coter client ....)
et après pas mal de recherches je n'ai vraiment aucune idée à part repartir sur un chat en ajax (qui serait un pas en arrière pour mon site)....

Je ne demande pas un code tout fais mais, juste être guider dans la démarche...

Cordialement,
Mout