1

非常に奇妙な問題があります。私は開いている WebSocket を持っています。通信は完全に機能します。上記の接続を介してサーバーに通知する、ウィンドウの onblur および onfocus イベントもあります。ただし、その場合、受け取る文字列は null で終了していません。それ以外の場合、それぞれのぼかし/フォーカスイベントで送信されるのと同じ文字列を送信する場合でも、通信は完全に完璧に機能します。それはなぜですか、どうすれば修正できますか?

ここにいくつかのコードがあります:

$(document).ready(function(){

    initializeEverything();

    window.onblur = function(){ notifyFocusChange(false); };

    window.onfocus = function(){ notifyFocusChange(true); };

});

function notifyFocusChange(present){

    if(present){
        webSocket.send('presence:present');
    }else{
        webSocket.send('presence:absent');
    }

}

そして、イベントが発生したときに受け取る null で終わらない文字列の例を次に示します。

presence:absentÏ┘ê÷/à°äJ÷ÝÿLÓ▓ùM÷Ýÿ[

編集:サーバーエラーである可能性があることが示唆されているため、受信メッセージをデコードするためのコードは次のとおりです。

private function decode($payload) {

    $length = ord($payload[1]) & 127;

    if ($length == 126) {
        $masks = substr($payload, 4, 4);
        $data = substr($payload, 8);
    } elseif ($length == 127) {
        $masks = substr($payload, 10, 4);
        $data = substr($payload, 14);
    } else {
        $masks = substr($payload, 2, 4);
        $data = substr($payload, 6);
    }

    $text = '';
    for ($i = 0; $i < strlen($data); ++$i) {
        $text .= $data[$i] ^ $masks[$i % 4];
    }

    return $text;

}

編集: Chrome でのみ発生します。同じ WebSocket プロトコルを使用する Firefox で確認したところ、すべて問題なく動作しました。

4

1 に答える 1

2

onblur および onfocus イベントは、おそらく立て続けに数回発生しています。websocket.send 呼び出しもすばやく複数回連続して呼び出されていることを意味します。

複数の送信呼び出しが十分に接近して発生する場合、サーバーでの 1 回の読み取りで複数のフレームを受信する可能性が高く、それが表示されていると思います。つまり、ペイロードの「ガベージ」は、実際には 1 つ以上の後続の WebSocket フレームです。

同じ Javascript コンテキストで 2 つの別々の送信を行うことで、問題を手動で再現できる場合があります。

function do_test () {
    ws.send("data1");
    ws.send("data2");
}

これにより、2 つの WebSocket フレームが十分に接近して送信されるため、サーバーはソケットから一度にすべてを読み取る可能性があります。

フレームを適切に処理するには、ペイロード長フィールドを解析し、指定された量のペイロード データのみを読み取り/マスク​​解除する必要があります。残っているものはすべて、新しいフレームの開始としてキューに入れる必要があります。

また、ソケットからの 1 回の読み取りで複数の Websocket フレームが返されるだけでなく、フレーム全体がフレームとして読み取られることに依存することはできません。1 回の読み取りでフレームの半分を読み取り、次のフレームで残りの半分を読み取る可能性があります。つまり、ソケットからの最初の読み取りでは、3 つの Websocket フレーム全体と 4 番目のフレームの 1 バイトを取得し、ソケットからの次の読み取りで 4 番目のフレームの残りを取得する場合があります。

これは一般的に次のように要約できます。WebSocket はメッセージ ベースのトランスポート プロトコルであり、TCP ソケットはストリーミング プロトコルです。WebSocket は TCP でレイヤー化されているため、基礎となるトランスポートがメッセージ ベースでなくても、WebSocket サーバー (およびクライアント) がアプリケーションにメッセージ全体を表示するために変換を行う必要があることを意味します。

于 2012-06-26T17:17:41.173 に答える