16

PHP で単純な websocket サーバーを開発しています。既存の実装がかなりあることは知っていますが、プロトコルをよりよく学ぶために自分で実装したいと思っています。ハンドシェイクをうまく行うことができ、クライアントはサーバーに接続しました。クライアントからのデータをデコードすることもできましたが、メッセージを送り返すのに問題があります。私の応答を受信すると、クライアントは切断されます。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;
}

更新: 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 に答える