Foros del Web » Programando para Internet » PHP »

websocket caracteres corruptos

Estas en el tema de websocket caracteres corruptos en el foro de PHP en Foros del Web. 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 ...
  #1 (permalink)  
Antiguo 03/11/2018, 18:13
Avatar de asdmaster  
Fecha de Ingreso: marzo-2010
Mensajes: 98
Antigüedad: 14 años, 1 mes
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.
  #2 (permalink)  
Antiguo 04/11/2018, 07:16
Avatar de asdmaster  
Fecha de Ingreso: marzo-2010
Mensajes: 98
Antigüedad: 14 años, 1 mes
Puntos: 2
Respuesta: websocket caracteres corruptos

Luego de revisar mucho código y leer la documentación de websocket entendí que mas que un error me faltaba implementar la parte del enmascaramiento.

https://developer.mozilla.org/es/doc...do_Data_Frames

Así que solo me falta comprobar en el servidor si los datos vienen enmascarados y proceder a "decodificarlos"

Código PHP:
Ver original
  1. private function seal($socketData) {
  2.         $b1 = 0x80 | (0x1 & 0x0f);
  3.         $length = strlen($socketData);
  4.  
  5.         if ($length <= 125)
  6.             $header = pack('CC', $b1, $length);
  7.         elseif ($length > 125 && $length < 65536)
  8.             $header = pack('CCn', $b1, 126, $length);
  9.         elseif ($length >= 65536)
  10.             $header = pack('CCNN', $b1, 127, $length);
  11.         return $header . $socketData;
  12.     }
  13.  
  14.     private function unseal($socketData) {
  15.         $length = ord($socketData[1]) & 127;
  16.         if ($length == 126) {
  17.             $masks = substr($socketData, 4, 4);
  18.             $data = substr($socketData, 8);
  19.         } elseif ($length == 127) {
  20.             $masks = substr($socketData, 10, 4);
  21.             $data = substr($socketData, 14);
  22.         } else {
  23.             $masks = substr($socketData, 2, 4);
  24.             $data = substr($socketData, 6);
  25.         }
  26.         $socketData = "";
  27.         for ($i = 0; $i < strlen($data); ++$i) {
  28.             $socketData .= $data[$i] ^ $masks[$i % 4];
  29.         }
  30.         return $socketData;
  31.     }

Etiquetas: caracteres, html, javascript, query, select
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 04:07.