Простой сервер websocket в PHP
Я разрабатываю простой сервер websocket в PHP. Я знаю, что существует довольно много существующих реализаций, но я хочу сделать так, чтобы лучше изучить протокол. Я сумел сделать handshaking тонкой и мои клиенты соединяются к серверу. Мне также удалось декодировать данные от клиента, но у меня проблемы с отправкой сообщений. Клиент отключается, когда получает мой ответ. Firefox говорит The connection to ws://localhost:12345/ was interrupted while the page was loading.
.
Я использовал этот ответ в качестве руководства.
Вот мой код для обертывания данных:
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: я попробовал его с Chrome, и я получил следующую ошибку, напечатанную на консоли: A server must not mask any frames that it sends to the client.
Я помещаю на сервер некоторые распечатки на консоли. Это базовый сервер эха. Я пытаюсь использовать aaaa
. Таким образом, фактическое обернутое сообщение должно быть 6 байтов. Правильно?
![enter image description here]()
Chrome печатает указанную выше ошибку. Также обратите внимание, что после переноса сообщения я просто пишу его в сокет:
$sent = socket_write($client, $bytesFormatted, strlen($bytesFormatted));
$this->say("! " . $sent);
Он печатает 6 значений, на самом деле 6 байтов записываются в провод.
Если я попытаюсь с помощью aaa
, Chrome не печатает ошибку, но также не вызывает мой обработчик onmessage. Он зависает, как ожидая большего количества данных.
Любая помощь высоко ценится. Спасибо.
Ответы
Ответ 1
У меня была та же проблема: для некоторых сообщений, отправленных с сервера, в браузере не было ответа, поскольку некоторая ошибка "Сервер не должен маскировать какие-либо фреймы..." был отображен, хотя я не добавлял никакой маски,
Причина была в рукопожатии.
Рукопожатие было:
"HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
...
"WebSocket-Location: ws://{$host}{$resource}\r\n\r\n" . chr(0)
Этот chr (0) был причиной, после того как я удалил все, все работает.
Ответ 2
Когда я писал свои классы websocket, у меня была такая же проблема.
В моем случае я использовал выходную буферизацию, чтобы определить, что я что-то повторил, прежде чем отправил ответ.
Можете попробовать это и посмотреть, если это проблема.