vue Fichiers liés au système de web socket
Kommunauty
Connexion
Inscription

Fichiers liés au système de web socket

le 20 janvier 2011 • Programmation • par openrpg

Vous souhaitez créer un système de web socket sur votre site et vous ne savez pas comment faire ?

Voici un exemple de tchat humain vs machine qui vous explique le fonctionnement de ce genre de programme.

client.php

Partie du script qui sera visible sur votre site internet (ou en local) via par exemple cette adresse : http://localhost/websocket/client.php

<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script type="text/javascript">
var socket;
var host = "ws://localhost:8080/websocket/startDaemon.php";
  
$(document).ready(function() {
  
  try
  {
    var socket = new WebSocket(host);
    
    message('<p class="event">Etat : '+socket.readyState);
    
    socket.onopen = function(){
      message('<p class="event">Etat : '+socket.readyState+' (Ouvert)');
    }
    
    socket.onmessage = function(msg){
      message('<p class="message">Reçu : '+msg.data);
    }
    
    socket.onclose = function(){
      message('<p class="event">Etat : '+socket.readyState+' (Fermer)');
    }      
  }
  catch(exception){ message('<p>Erreur : '+exception); }
  
  function send()
  {
    var text = $('#text').val();
    if(text=="")
    {
      message('<p class="warning">Veuillez indiquer un message');
      return ;  
    }
    
    try
    {
      socket.send(text);
      message('<p class="event">Envois : '+text)
    }
    catch(exception){ message('<p class="warning">'); }
    
    $('#text').val("");
  }
  
  function message(msg)
  {
    $('#chatLog').append(msg+'</p>');
  }
  
  $('#text').keypress(function(event) {
    if (event.keyCode == '13') {
      send();
    }
  });  
  
  $('#send').click(function(){ send(); });
  
  $('#disconnect').click(function(){ socket.close(); });
      
});
</script>
<meta charset=utf-8 />
<style type="text/css">
body {
  font-family:Arial, Helvetica, sans-serif;
}
#chatLog {
  padding:5px;
  border:1px solid black;
}
#chatLog p {
  margin:0;
}
.event {
  color:#999;
}
.warning {
  font-weight:bold;
  color:#CCC;
}
</style>
<title>WebSockets Client</title>
</head>
<body>
<h1>WebSockets</h1>
<div id="chatLog"></div>
<p id="examples">Taper : 'bonjour', 'nom', 'age', 'date'</p>
<input id="text" type="text" />
<button id="send">Envoyer</button>
<button id="disconnect">Deconnexion</button>
</body>
</html>


startDaemon.php

Ce fichier est celui qu'il faut lancer pour activer le serveur. Il doit être lancé via votre terminal avec cette commande : $ php -q /le/chemin/du/fichier/startDaemon.php

Il réunit tout le fichier au bon fonctionnement du programme et initialise l'objet "new socketWebSocket" a qui nous avons passé 2 arguments, le premier est l'adresse du server websocket et le deuxième est le port sur lequel nous interrogeons le programme ici on est en local donc "localhost" et j'ai choisi d'utiliser le port "8080"

<?php
ob_implicit_flush(true);
require_once 'socket.class.php';
require_once 'socketWebSocket.class.php';
require_once 'trigger.class.php';
new socketWebSocket('localhost',8080);
?>

socket.class.php

Ce fichier gère la création du websocket et son initialisation. Il contient la classe parent qui par la suite aura 1 héritier et un sous héritier.

<?php
class socket
{
  protected $master, $allsockets = array();
  
  public function __construct( $host='localhost', $port=8080 )
  {
    $this->createSocket($host,$port);
  }
  
  private function createSocket( $host, $port )
  {
    if( ( $this->master = socket_create(AF_INET,SOCK_STREAM,SOL_TCP) ) < 0 )
      die('socket_create() erreur : '.socket_strerror($this->master));
  
    self::console('Socket '.$this->master.' créé.');
  
    socket_set_option($this->master,SOL_SOCKET,SO_REUSEADDR,1);
  
    if( ( $ret = socket_bind($this->master,$host,$port) ) < 0 )
      die('socket_bind() erreur : '.socket_strerror($ret));
  
    self::console('Socket connecté '.$host.':'.$port);
  
    if( ( $ret = socket_listen($this->master,5) ) < 0 )
      die('socket_listen() erreur : '.socket_strerror($ret));
  
    self::console('Debut de l\'écoute.');
  
    $this->allsockets[] = $this->master;
  }
  
  protected function console( $msg, $type = 'System' )
  {
    $msg = explode("\n",$msg);
    foreach( $msg as $line )
      echo date('Y-m-d H:i:s') . ' '.$type.' : '.$line."\n";
  }
  
  protected function send($client,$msg)
  {
    socket_write($client, $msg,strlen($msg));
  }
}
?>


socketWebSocket.class.php

Ce fichier est le coeur de notre websocket. Il gère la boucle qui reçoit/envoie les informations aux diverses connexions qui lui sont liées. Il gère aussi les connexions proprement dites et aussi les déconnexions

<?php
class socketWebSocket extends socket
{
  private $clients = array(), $handshakes = array();
  
  public function __construct()
  {
    parent::__construct();
    self::run();
  }
  
  protected function console( $msg, $type='WebSocket' )
  {
    parent::console( $msg, $type );
  }
  
  protected function send( $client, $msg )
  {
    self::console('> '.$msg);
    parent::send($client,chr(0).$msg.chr(255));
  }
  
  private function run()
  {
    while(true)
    {
      $changed_sockets = $this->allsockets;
  
      $num_sockets = socket_select($changed_sockets,$write=NULL,$exceptions=NULL,NULL);
  
      foreach( $changed_sockets as $socket )
      {
        if( $socket == $this->master )
        {
          if( ($client=socket_accept($this->master)) < 0 )
          {
            console('socket_accept() erreur : '. socket_strerror(socket_last_error($client)));
            continue;
          }
          else
          {
            $this->allsockets[] = $client;
            $socket_index = array_search($client,$this->allsockets);
            $this->clients[$socket_index] = new stdClass;
            $this->clients[$socket_index]->socket_id = $client;
  
            self::console($client . ' connecté!');
          }
        }
        else
        {
          $socket_index = array_search($socket,$this->allsockets);
  
          $bytes = socket_recv($socket,$buffer,2048,0);
          
          if( $bytes === 0 )
            self::disconnected($socket);
  
          else
          {
            if( !isset($this->handshakes[$socket_index]) )
            {
              self::do_handshake($buffer,$socket,$socket_index);
              self::send($socket,'connexion');
            }
            else
            {
              if(!$action = substr($buffer,1,$bytes-2))
                self::disconnected($socket);
  
              else
              {
                self::console('< '.$action);
                
                $action = str_replace(array(' ','\'','-',','),'_',$action);
                if( method_exists('trigger',$action) )
                  self::send($socket,trigger::$action());
              }
            }
          }
        }
      }
    }
  }
  
  private function do_handshake($buffer,$socket,$socket_index)
  {
    self::console('Requete handshake...');
  
    list($resource,$host,$origin,$key1,$key2,$l8b) = self::getheaders($buffer);
  
    self::console('Handshaking...');
    
    $upgrade  = "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" .
                "Upgrade: WebSocket\r\n" .
                "Connection: Upgrade\r\n" .
                "Sec-WebSocket-Origin: {$origin}\r\n" .
                "Sec-WebSocket-Location: ws://{$host}{$resource}\r\n" .
                "\r\n" . self::calcKey($key1,$key2,$l8b) . "\r\n";
          
    $this->handshakes[$socket_index] = true;
  
    socket_write($socket,$upgrade.chr(0),strlen($upgrade.chr(0)));
  
    self::console('Handshaking effectué...');
  }
  
  private static function calcKey($key1,$key2,$l8b)
  {
    preg_match_all('/([\d]+)/', $key1, $key1_num);
    preg_match_all('/([\d]+)/', $key2, $key2_num);
    
    $key1_num = implode($key1_num[0]);
    $key2_num = implode($key2_num[0]);
    
    preg_match_all('/([ ]+)/', $key1, $key1_spc);
    preg_match_all('/([ ]+)/', $key2, $key2_spc);
    
    $key1_spc = strlen(implode($key1_spc[0]));
    $key2_spc = strlen(implode($key2_spc[0]));
    
    if( $key1_spc==0|$key2_spc==0 )
    {
      self::console('Key invalide');
      return false;
    }
    
    $key1_sec = pack("N",$key1_num / $key1_spc);
    $key2_sec = pack("N",$key2_num / $key2_spc);
    
    return md5($key1_sec.$key2_sec.$l8b,1);
  }
  
  private function disconnected($socket)
  {
    if( $index = array_search($socket, $this->allsockets) )
      unset($this->allsockets[$index], $this->clients[$index], $this->handshakes[$index]);
  
    socket_close($socket);
    self::console($socket.' deconnexion');
  }
  
  private static function getheaders($req)
  {
    $r = $h = $o = NULL;
    
    if(preg_match("/GET (.*) HTTP/" ,$req,$match))
      $r = $match[1];
    if(preg_match("/Host: (.*)\r\n/" ,$req,$match))
      $h = $match[1];
    if(preg_match("/Origin: (.*)\r\n/" ,$req,$match))
      $o = $match[1];
    if(preg_match("/Sec-WebSocket-Key1: (.*)\r\n/",$req,$match))
      $sk1 = $match[1];
    if(preg_match("/Sec-WebSocket-Key2: (.*)\r\n/",$req,$match))
      $sk2 = $match[1];
    if($match=substr($req,-8))
      $l8b = $match;
      
    return array($r, $h, $o, $sk1, $sk2, $l8b );
  }
}
?>


trigger.class.php

Ce fichier quant à lui est présent pour la démonstration, il exécutera des méthodes selon les appels effectué via le fichier client.php. Si dans le input on tape bonjour, c'est la méthode bonjour() qui sera exécutée. Par contre si on tape salut vu qu'on a aucune méthode de ce nom, aucun retour ne sera fait.

Vous pouvez en créer autant que vous le souhaitez.

<?php
class trigger extends socketWebSocket
{
    protected static function bonjour()
    {
      return 'Bonjour, comment allez vous ?';
    }
    
    protected static function nom()
    {
      return 'Mon nom est alban';
    }  
    
    protected static function date()
    {
      return date('d-m-Y');
    }  
    
    protected static function age()
    {
      return 'J\'ai 28 ans';
    }  
    
    protected static function as_tu_l_heure()
    {
      return date('H:i:s');
    }      
}
?>


Téléchargement

Pour télécharger la totalité du script , rendez vous à cette adresse :

Script entier



  
Aucun commentaire

Sois le premier à débuter une discussion à propos de cet article !



Ajoute un commentaire !

Ajouter une image... Trouvée sur internet » De mon PC »
Adresse URL :
Adresse de la page de la vidéo :
Taille du texte :
Couleur du texte :

Article lu 7176 fois.