Ver Mensaje Individual
  #1 (permalink)  
Antiguo 03/11/2018, 18:13
Avatar de asdmaster
asdmaster
 
Fecha de Ingreso: marzo-2010
Mensajes: 98
Antigüedad: 14 años, 2 meses
Puntos: 2
websocket caracteres corruptos

Tengo problemas para implementar un socket server con PHP, he realizado pruebas con diferentes clientes sin problemas, pero cuando uso websocket en Chrome o Firefox las cadenas se corrompen por alguna razón que desconozco, sospecho que el problema se encuentra en el “apretón de manos” agradeceré cualquier ayuda porque ya estoy dando vueltas en circulo.

Aquí dejo el código esperando su ayuda, gracias

server socket
Código PHP:
Ver original
  1. <?php
  2.  
  3. class MySocketServer {
  4.  
  5.     protected $socket;
  6.     protected $clients = [];
  7.     protected $changed;
  8.  
  9.     public function __construct($host, $port) {
  10.         set_time_limit(0);
  11.         $this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)
  12.                 or die("error: " . socket_strerror(socket_last_error()));
  13.         socket_set_option($this->socket, SOL_SOCKET, SO_REUSEADDR, 1);
  14.         //bind socket to specified host
  15.         socket_bind($this->socket, $host, $port)
  16.                 or die("error: " . socket_strerror(socket_last_error(socket_last_error($this->socket))));
  17.         //listen to port
  18.         socket_listen($this->socket)
  19.                 or die("error: " . socket_strerror(socket_last_error(socket_last_error($this->socket))));
  20.     }
  21.  
  22.     public function __destruct() {
  23.         foreach ($this->clients as $client) {
  24.             socket_close($client);
  25.         }
  26.         socket_close($this->socket);
  27.     }
  28.  
  29.     public function run() {
  30.         // create a list of all the clients that will be connected to us..
  31.         // add the listening socket to this list
  32.         $this->clients = array($this->socket);
  33.         while (true) {
  34.             // create a copy, so $clients doesn't get modified by socket_select()
  35.             // reset changed
  36.             $this->changed = $this->clients;
  37.  
  38.             // get a list of all the clients that have data to be read from
  39.             // if there are no clients with data, go to next iteration
  40.             $write = $except = NULL;
  41.             if (socket_select($this->changed, $write, $except, 0) > 0) {
  42.                 $this->checkNewClients();
  43.                 $this->checkMessageRecieved();
  44.                 $this->checkDisconnect();
  45.             }
  46.         }
  47.     }
  48.  
  49.     private function checkNewClients() {
  50.         $this->log("checkNewClients...");
  51.  
  52.         // check if there is a client trying to connect
  53.         if (in_array($this->socket, $this->changed)) {
  54.             // accept the client, and add him to the $clients array
  55.             $this->clients[] = $newsock = socket_accept($this->socket);
  56.  
  57.             // $header = socket_read($newsock, 2048, PHP_NORMAL_READ);
  58.             // @socket_recv($newsock, $header, 1024, 0);
  59.             if ((int) @socket_recv($newsock, $header, 2048, MSG_DONTWAIT) > 0) {
  60.                 $handshake = $this->handshake($header);
  61.                 $this->log("handshake: " . $handshake);
  62.                 socket_write($newsock, $handshake, strlen($handshake));
  63.             }
  64.  
  65.             socket_getpeername($newsock, $ip);
  66.             $this->log("There are " . (count($this->clients) - 1) . " client(s) connected to the server\n");
  67.             $this->log("New client connected: " . $ip);
  68.  
  69.             // remove the listening socket from the clients-with-data array
  70.             $key = array_search($this->socket, $this->changed);
  71.             unset($this->changed[$key]);
  72.         }
  73.     }
  74.  
  75.     private function checkMessageRecieved() {
  76.         foreach ($this->changed as $key => $socket) {
  77.             $buffer = null;
  78.             while (socket_recv($socket, $buffer, 1024, 0) > 0) {
  79.                 $this->log(trim("Client Message: " . $buffer));
  80.                 unset($this->changed[$key]);
  81.                 break;
  82.             }
  83.         }
  84.     }
  85.  
  86.     private function checkDisconnect() {
  87.         foreach ($this->changed as $changed_socket) {
  88.             $buf = @socket_read($changed_socket, 1024, PHP_NORMAL_READ);
  89.             if ($buf !== false) {
  90.                 continue;
  91.             }
  92.             // remove client for $clients array
  93.             $found_socket = array_search($changed_socket, $this->clients);
  94.             socket_getpeername($changed_socket, $ip);
  95.             unset($this->clients[$found_socket]);
  96.             $this->log('client ' . $ip . ' has disconnected');
  97.         }
  98.     }
  99.  
  100.     function handshake($header) {
  101.         $handshake = '';
  102.         $this->log('header ' . $header);
  103.         if (preg_match("/Sec-WebSocket-Version: (.*)\r\n/", $header, $match)) {
  104.             $version = $match[1];
  105.         } else {
  106.             $this->log("The client doesn't support WebSocket");
  107.         }
  108.  
  109.         if ($version == 13) {
  110.             if (preg_match("/GET (.*) HTTP/", $header, $match))
  111.                 $root = $match[1];
  112.             if (preg_match("/Host: (.*)\r\n/", $header, $match))
  113.                 $host = $match[1];
  114.             if (preg_match("/Origin: (.*)\r\n/", $header, $match))
  115.                 $origin = $match[1];
  116.             if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $header, $match))
  117.                 $key = $match[1];
  118.  
  119.             $acceptKey = $key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
  120.             $acceptKey = base64_encode(sha1($acceptKey, true));
  121.  
  122.             $handshake .= "HTTP/1.1 101 Switching Protocols\r\n" .
  123.                     "Upgrade: websocket\r\n" .
  124.                     "Connection: Upgrade\r\n" .
  125.                     "Sec-WebSocket-Accept: $acceptKey" .
  126.                     "\r\n\r\n";
  127.         } else {
  128.             $this->log("WebSocket version 13 required (the client supports version {$version})");
  129.         }
  130.         return $handshake;
  131.     }
  132.  
  133.     private function sendMessage($msg) {
  134.         foreach ($this->clients as $client) {
  135.             socket_write($client, $msg, strlen($msg));
  136.         }
  137.         return true;
  138.     }
  139.  
  140.     private function log($msg) {
  141.         echo "\r\n$msg\r\n";
  142.     }
  143.  
  144. }
  145.  
  146. require_once ('config.php');
  147. (new MySocketServer($host, $port))->run();


websocket
Código PHP:
Ver original
  1. <?php require_once ('config.php'); ?>
  2. <!DOCTYPE html>
  3. <meta charset="utf-8" />
  4. <title>WebSocket Test</title>
  5. <script language="javascript" type="text/javascript">
  6.     var websocket;
  7.     window.onload = function () {
  8.         websocket = new WebSocket('<?php echo "ws://{$host}:{$port}"; ?>');
  9.         websocket.onopen = function (evt) {
  10.             console.log("connected..");
  11.         };
  12.         websocket.onclose = function (evt) {
  13.             console.log("websocket close");
  14.         };
  15.         websocket.onmessage = function (evt) {
  16.             console.log(event.data);
  17.         };
  18.         websocket.onerror = function (evt) {
  19.             console.log(event.data);
  20.         };
  21.         document.querySelector("#send").addEventListener("click", function () {
  22.             websocket.send(document.querySelector("#message").value);
  23.         });
  24.     };
  25. </script>
  26. <h2>WebSocket Test</h2>
  27. <input type="text" id="message" name="message" value="" />
  28. <input type="button" id="send" name="send" value="Enviar" />

Obtengo esta salida, como pueden ver el mensaje enviado con el navegador no llega correctamente.