2

socketo.meサイトの指示に従って、Ratchet for php を使用して websockets を機能させようとしています。指示に従って、composer.json ファイルに Ratchet バージョン 0.2.* が必要でした。私は php 5.4.9-4ubuntu2 と Apache 2 を使用しています。ブラウザには Firefox 21.0 と Chrome 26.0.1410.63 を使用しています。このサイトによると、Rachet は Firefox 6-20 と Chrome 13-26 をサポートしていますが、Firefox 21 を使用した場合と Chrome 26 を使用した場合の結果はほぼ同じです。

MessageComponentInterface を実装するクラスを次に示します。

<?php
namespace WebsocketTest;

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;

require dirname (__DIR__).'/../../../../vendor/autoload.php';

class Chat implements MessageComponentInterface
{
    protected $clients;

    public function __construct ()
    {
        $this->clients = new \SplObjectStorage;
    }

    public function onOpen (ConnectionInterface $conn)
    {
        // Store the new connection to send messages to later
        $this->clients->attach ($conn);
        echo "New connection! ({$conn->resourceId})\n";
    }

    public function onMessage (ConnectionInterface $from, $msg)
    {
        $numRecv = count ($this->clients) - 1;
        echo sprintf ('Connection %d sending message "%s" to %d other connection%s'."\n", $from->resourceId, $msg, $numRecv, $numRecv == 1 ? '' : 's');

        foreach ($this->clients as $client)
        {
            if ($from !== $client)
            {
                // The sender is not the receiver, send to each client connected
                $client->send ($msg);
            }
        }
    }

    public function onClose (ConnectionInterface $conn)
    {
        // The connection is closed, remove it, as we can no longer send it messages
        $this->clients->detach ($conn);
        echo "Connection {$conn->resourceId} has disconnected\n";
    }

    public function onError (ConnectionInterface $conn, \Exception $e)
    {
        echo "An error has occurred: {$e->getMessage()}\n";
        $conn->close ();
    }
}

これが私のシェルスクリプトコードです。

<?php
use Ratchet\Server\IoServer;
use WebsocketTest\Chat as Chat;

require_once __DIR__.'/Chat.php';

$server = IoServer::factory (new Chat (), 8080);
$server->run ();

これがシェルスクリプトから得た出力です。

New connection! (38)
Connection 38 sending message "GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: www.zf2.dev:8080
Origin: http://www.zf2.dev
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: YHbsxEgVhWTDJjaBJAGHdQ==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: x-webkit-deflate-frame

" to 1 other connection
New connection! (39)
Connection 39 sending message "GET / HTTP/1.1
Host: www.zf2.dev:8080
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:21.0) Gecko/20100101 Firefox/21.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Sec-WebSocket-Version: 13
Origin: http://www.zf2.dev
Sec-WebSocket-Key: EPpLFS3bXx/eC+WaoNDacA==
Connection: keep-alive, Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket

" to 2 other connections
Connection 37 has disconnected
Connection 38 has disconnected

これが私のJavaScriptコードです。接続が作成されたら、JavaScript コンソールに出力します。

var conn = null;
function test_websockets ()
{
    conn = new WebSocket ('ws://www.zf2.dev:8080');
    console.log (conn);
    conn.onopen = function (e) { console.log ("Connection established!"); };
    conn.onmessage = function (e) { console.log (e.data); };
    conn.onclose = function (e) { console.log ('closed') };
//  conn.send ('sending message from the client');
}

function test_ws_message ()
{
    conn.send ('the test message');
}

これは、Chrome の JavaScript コンソールで取得した出力です。

WebSocket {binaryType: "blob", extensions: "", protocol: "", onclose: null, onerror: null…}
 html5test.js:34
Uncaught Error: InvalidStateError: DOM Exception 11 html5test.js:47
test_ws_message html5test.js:47
onclick

これは、Firefox の Firebug から得た出力です。

WebSocket { url="ws://www.zf2.dev:8080", readyState=0, bufferedAmount=0, more...}
html5test.js (line 34)
InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable
[Break On This Error]   

conn.send ('the test message');

html5test.js (line 47)
closed
html5test.js (line 38)
Firefox can't establish a connection to the server at ws://www.zf2.dev:8080/.


conn = new WebSocket ('ws://www.zf2.dev:8080');

Firefox では接続がすぐに閉じられたことが示されますが、Chrome ではそうではないことに注意してください。ただし、Chrome では接続が開かれたことが表示されないため、どちらのブラウザーでも動作しているとは思いません。サーバースクリプトは接続が確立されたと考えているようですが、どちらのブラウザにも「接続が確立されました!」と表示されることはありません。onopen メソッドが呼び出されたことを示すメッセージ。互換性のないバージョンの websockets の「ハンドシェイク」が原因でこの問題が発生する可能性があることを示唆するコメントを 1 つ見つけることができましたが、Ratchet の他のバージョンに関する情報や、互換性のあるバージョンをクライアントで実行するために何をする必要があるかについての情報は見つかりませんでした。サーバ。また、onopen がまったく呼び出されない場合があるというコメントもいくつか見つかりましたが、これは信じがたいことです。

4

2 に答える 2

6

Ratchet のドキュメントと RFC6455 に正しく従うと、Websocket 接続要求が行われると、特定の応答がクライアントに送信されることに気付くでしょう。応答が受信されない場合、クライアントは接続が確立されていないと想定します。

あなたの場合の問題はMessageComponentInterface、接続を処理している が接続時にソケット応答で応答しないことです。WsServerただし、Ratchet は、Chat クラスのオブジェクトを渡すことができ、目的の操作を実現できる、呼び出された実装済みのクラスにバンドルされています。ただし、WsServer は ではありませんが、幸運にも Ratchet にバンドルされてMessageComponentInterfaceいる 内にラップすると、問題は解決します。HttpServer

したがって、新しいコードは次のようになります。

$server = IoServer::factory (new HttpServer(new WsServer(new Chat ())), 8080);

もちろん、名前空間に WsServer と HttpServer を追加する必要があります。

于 2014-11-10T01:55:31.603 に答える
4

使用する

$server = IoServer::factory (new HttpServer(new WsServer(new Chat())), 8080);

それ以外の

$server = IoServer::factory (new Chat (), 8080);
于 2013-08-03T13:13:59.610 に答える