2011-08-17 27 views
7

Así que Chrome 14 ha implementado la versión hybi10 de websockets. Tengo un programa interno que nuestra empresa utiliza a través de Chrome que usa websockets que se rompe con este cambio.PHP Websocket Server hybi10

¿Alguien ha tenido éxito al enmarcar los datos usando un servidor php? Puedo hacer que funcione el nuevo apretón de manos, pero parece que no puedo entender el encuadre. Hay un ejemplo de Python aquí https://github.com/kanaka/websockify/blob/master/websocket.py#L233 pero estoy teniendo dificultades para convertir esto a php, ¿alguien tiene alguna sugerencia?

Debo mencionar que la función en cuestión en el ejemplo de python es decode_hybi().

+1

Quizás esta pregunta le resulte interesante: http://stackoverflow.com/questions/7040078/not-sure-how-to-frame-data-in -websockets-draft-08. Traté de explicar cómo funciona el nuevo encuadre; tal vez ayuda. – pimvdb

+0

Esto fue útil gracias! Publicaré la solución en PHP para otros. – jivetek

Respuesta

6

i acaba de terminar una wich clase hace que el PHP-WebSocket-Servidor de Nico Kaiser (https://github.com/nicokaiser/php-websocket) capaz de manejar hybi 10-marcos y apretón de manos. Puede descargar la nueva clase aquí: http://lemmingzshadow.net/386/php-websocket-serverclient-nach-draft-hybi-10/ (Connection.php)

+0

Gracias por esto. Originalmente estaba usando esta implementación también. ¡Definitivamente mejoraste mi código y me ahorraste tiempo implementando una solución completa! – jivetek

3

Este código asume que no hay errores o marcos mal formados y se basa en esta respuesta - How to (de)construct data frames in WebSockets hybi 08+?.

Este código es muy básico y está lejos de ser una solución completa. Funciona para mis propósitos (que son bastante básicos). Con suerte, es útil para otros.

function handle_data($data){ 
    $bytes = $data; 
    $data_length = ""; 
    $mask = ""; 
    $coded_data = "" ; 
    $decoded_data = "";   
    $data_length = $bytes[1] & 127; 
    if($data_length === 126){ 
     $mask = substr($bytes, 4, 8); 
     $coded_data = substr($bytes, 8); 
    }else if($data_length === 127){ 
     $mask = substr($bytes, 10, 14); 
     $coded_data = substr($bytes, 14); 
    }else{ 
     $mask = substr($bytes, 2, 6); 
     $coded_data = substr($bytes, 6); 
    } 
    for($i=0;$i<strlen($coded_data);$i++){ 
     $decoded_data .= $coded_data[$i]^$mask[$i%4]; 
    } 
    $this->log("Server Received->".$decoded_data); 
    return true; 
} 

Este es el código para enviar datos de vuelta. De nuevo, esto es bastante básico, supone que está enviando un solo marco de texto. Sin marcos de continuación, etc. No hay errores de verificación tampoco. Espero que otros lo encuentren útil.

public function send($data) 
{ 
    $frame = Array(); 
    $encoded = ""; 
    $frame[0] = 0x81; 
    $data_length = strlen($data); 

    if($data_length <= 125){ 
     $frame[1] = $data_length;  
    }else{ 
     $frame[1] = 126; 
     $frame[2] = $data_length >> 8; 
     $frame[3] = $data_length & 0xFF; 
    } 

    for($i=0;$i<sizeof($frame);$i++){ 
     $encoded .= chr($frame[$i]); 
    } 

    $encoded .= $data; 
    write_to_socket($this->socket, $encoded); 
    return true;  
} 
+1

Genial, lograste hacerlo funcionar. Puede elegir si desea codificar sus datos de servidor a cliente. Sin embargo, debería comenzar de nuevo con '1000 0001' y luego con otro byte que comience con' 0' (si no lo enmascara), y use el mismo formato para la longitud (esto es obligatorio; la máscara no está de acuerdo con el especificaciones). – pimvdb

+1

¡Gracias de nuevo por su ayuda! Logré hacer que esta parte funcionara también. Copiaré mi código a continuación para que otros puedan usarlo. – jivetek

+0

Gracias por publicar su solución; ¡eso es ciertamente útil para otros! – pimvdb