2012-10-29 22 views
15

Zajmuję się tworzeniem prostego serwera websocket w PHP. Wiem, że istnieje sporo istniejących implementacji, ale chcę stworzyć własne, aby lepiej poznać ten protokół. Udało mi się zrobić grzywnę uzgadniania i moi klienci łączą się z serwerem. Udało mi się również odkodować dane od klienta, ale mam problem z odesłaniem wiadomości. Klient rozłącza się, gdy otrzyma moją odpowiedź. Firefox mówi: The connection to ws://localhost:12345/ was interrupted while the page was loading..Prosty serwer WWW w PHP

Użyłem jako przewodnika this answer.

Oto mój kod do owijania dane:

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: próbowałem go z Chrome i mam następujący błąd, wydrukowany w konsoli: A server must not mask any frames that it sends to the client.

I umieścić niektóre konsolę wydruki na serwerze. Jest to podstawowy serwer echa. Próbuję z aaaa. Rzeczywisty zawinięty komunikat musi mieć 6 bajtów. Dobrze?

enter image description here

Chrome wyświetla powyższy błąd. Należy również zauważyć, że po owinięciu komunikat po prostu napisać go do gniazda:

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

Drukuje 6 sens 6 bajtów są rzeczywiście napisane do drutu.

Jeśli spróbuję z aaa, Chrome nie wydrukuje błędu, ale nie wywoła też funkcji obsługi wiadomości na mój temat. Wisi tak, jakby czekał na więcej danych.

Każda pomoc bardzo ceniona. Dzięki.

+0

Użyłeś wireshark do sprawdzenia, czy bajty wysyłane przez przewód odpowiadają temu, co wydaje się być wygenerowane tutaj? I że żaden inny kod nie wysyła dodatkowych danych, które mogą być interpretowane jako początek wiadomości? – simonc

+0

@ simonc Jest na tej samej maszynie, więc myślę, że wireshark nie widzi pakietów. Spróbuję to jakoś obwąchać. Dzięki. –

+0

Czy masz drugi komputer, na którym można tymczasowo uruchomić przeglądarkę Firefox? – simonc

Odpowiedz

3

Miałem ten sam problem: dla niektórych wiadomości wysłanych z serwera nie było odpowiedzi w przeglądarce, dla niektórych wyświetlany był błąd "Serwer nie może maskować żadnych ramek ...", ale nie dodałem żadnych maska. Powód był w potwierdzeniu uścisku dłoni. Uzgadnianie było:

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

To Chr (0) było powodem, po tym jak usunięto go wszystko działa.

+0

Jesteś geniuszem. Dziękuję Ci. –

1

Kiedy napisałem klasy websocket, miałem ten sam problem. W moim przypadku użyłem bufora wyjściowego do stwierdzenia, że ​​coś podobnego brzmiało coś przed wysłaniem odpowiedzi. Może spróbujemy tego i zobaczymy, czy to jest problem.