16

我正在用 PHP 开发一个简单的 websocket 服务器。我知道有很多现有的实现,但我想自己做,以便更好地学习协议。我设法很好地握手,我的客户连接到服务器。我还设法解码了来自客户端的数据,但我在发回消息时遇到了问题。客户端收到我的回复后断开连接。火狐说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;
}

更新:我用 Chrome 尝试过,我得到了以下错误,打印在控制台中:A server must not mask any frames that it sends to the client.

我在服务器上放了一些控制台打印输出。它是一个基本的回声服务器。我尝试使用aaaa. 所以实际包装的消息必须是 6 个字节。对?

在此处输入图像描述

Chrome 打印出上述错误。另请注意,包装消息后,我只需将其写入套接字:

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

它打印 6 表示实际将 6 个字节写入线路。

如果我尝试使用aaa,Chrome 不会打印错误,但也不会调用我的 onmessage 处理程序。它挂起,好像在等待更多数据。

任何帮助高度赞赏。谢谢。

4

2 回答 2

4

我遇到了同样的问题:对于从服务器发送的一些消息,浏​​览器中没有响应,对于一些错误“服务器不能屏蔽任何帧......”,尽管我没有添加任何掩码。原因在于发送的握手。握手是:

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

那个 chr(0) 是原因,在我删除它之后一切正常。

于 2012-11-08T18:55:31.293 回答
1

当我编写 websocket 类时,我遇到了同样的问题。就我而言,我使用输出缓冲来确定我在发送回复之前正在回显某些内容。可以试试看是不是问题。

于 2012-11-08T00:00:10.400 回答