2012-10-29 13 views
15

Ich entwickle einen einfachen Websocket-Server in PHP. Ich weiß, dass es einige existierende Implementierungen gibt, aber ich möchte meine eigenen erstellen, um das Protokoll besser zu lernen. Es ist mir gelungen, das Handshake-Gut zu machen und meine Clients verbinden sich mit dem Server. Ich habe es auch geschafft, die Daten vom Client zu entschlüsseln, aber ich habe Probleme beim Zurücksenden von Nachrichten. Der Client trennt die Verbindung, wenn er meine Antwort erhält. Firefox sagt The connection to ws://localhost:12345/ was interrupted while the page was loading..Einfacher Websocket-Server in PHP

Ich habe this answer als Leitfaden verwendet.

Hier ist mein Code, um die Daten für die Verpackung:

private function wrap($msg = ""){ 
    $length = strlen($msg); 
    $this->log("wrapping (" . $length . " bytes): " . $msg); 

    $bytesFormatted = chr(129); 
    if($length <= 125){ 
     $bytesFormatted .= chr($length); 
    } else if($length >= 126 && $length <= 65535) { 
     $bytesFormatted .= chr(126); 
     $bytesFormatted .= chr(($length >> 8) & 255); 
     $bytesFormatted .= chr(($length  ) & 255); 
    } else { 
     $bytesFormatted .= chr(127); 
     $bytesFormatted .= chr(($length >> 56) & 255); 
     $bytesFormatted .= chr(($length >> 48) & 255); 
     $bytesFormatted .= chr(($length >> 40) & 255); 
     $bytesFormatted .= chr(($length >> 32) & 255); 
     $bytesFormatted .= chr(($length >> 24) & 255); 
     $bytesFormatted .= chr(($length >> 16) & 255); 
     $bytesFormatted .= chr(($length >> 8) & 255); 
     $bytesFormatted .= chr(($length  ) & 255); 
    } 

    $bytesFormatted .= $msg; 
    $this->log("wrapped (" . strlen($bytesFormatted) . " bytes): " . $bytesFormatted); 
    return $bytesFormatted; 
} 

UPDATE: Ich versuchte es mit Chrome und ich bekam die folgenden Fehler, in der Konsole ausgegeben: A server must not mask any frames that it sends to the client.

ich eine Konsole setzen Ausdrucke auf dem Server. Es ist ein einfacher Echo-Server. Ich versuche es mit . Daher muss die tatsächliche umschlossene Nachricht 6 Byte lang sein. Recht?

enter image description here

Chrome druckt den obigen Fehler. Beachten Sie, dass auch nach der Nachricht Einwickeln Ich schreibe es einfach an der Steckdose:

$sent = socket_write($client, $bytesFormatted, strlen($bytesFormatted)); 
$this->say("! " . $sent); 

Er druckt 6 Bedeutung 6 Bytes an den Draht tatsächlich geschrieben werden.

Wenn ich versuche, mit aaa, Chrome druckt nicht den Fehler, aber nicht meine onmessage-Handler entweder. Es hängt, als ob auf mehr Daten gewartet wird.

Jede Hilfe sehr geschätzt. Vielen Dank.

+0

Haben Sie mit wireshark überprüft, dass die Bytes, die über die Leitung gesendet werden, mit dem übereinstimmen, was hier im Code generiert wird? Und dass kein anderer Code zusätzliche Daten sendet, die als Start einer Nachricht interpretiert werden könnten? – simonc

+0

@simonc Es ist auf der gleichen Maschine, so denke ich, dass wireshark die Pakete nicht sehen kann. Ich werde versuchen, es irgendwie zu schnüffeln. Vielen Dank. –

+0

Haben Sie eine zweite Maschine, auf der Sie Firefox vorübergehend ausführen können? – simonc

Antwort

3

Ich hatte das gleiche Problem: Für einige Nachrichten vom Server gab es keine Antwort im Browser, für einige der Fehler "Ein Server darf keine Frames maskieren ..." angezeigt wurde, obwohl ich keine hinzufügen Maske. Der Grund wurde im Handshake gesendet. Der Händedruck war:

"HTTP/1.1 101 Web Socket Protocol Handshake\r\n" . 
... 
"WebSocket-Location: ws://{$host}{$resource}\r\n\r\n" . chr(0) 

Das chr (0) war der Grund, nachdem ich es entfernt alles funktioniert.

+0

Sie sind ein Genie. Vielen Dank. –

1

Als ich meine Websocket-Klassen schrieb, hatte ich das gleiche Problem. In meinem Fall habe ich Ausgabepufferung verwendet, um zu bestimmen, dass ich etwas aus Echo gesendet habe, bevor ich die Antwort sendete. Könnte es versuchen und sehen, ob es das Problem ist.