【问题标题】:Websockets with Ratchet close immediately带有 Ratchet 的 Websocket 立即关闭
【发布时间】:2013-06-05 13:47:56
【问题描述】:

使用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。 This site 说 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 ();
    }
}

这是我的 shell 脚本代码。

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

require_once __DIR__.'/Chat.php';

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

这是我从 shell 脚本得到的输出。

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“握手”可能会导致这种情况发生,但我从未找到任何有关其他版本的 Ratchet 或我需要做些什么才能让兼容版本在客户端上运行和服务器。我还发现一些 cmets 说有时 onopen 根本不会被调用,我很难相信。任何关于问题可能是什么或如何解决它的想法将不胜感激。

【问题讨论】:

  • 看起来您的客户端在收到来自服务器的消息时正在断开连接,这发生在 onMessage() 中,因此当服务器收到来自客户端的消息时。能否贴出将消息发送到服务器的客户端代码?
  • 我实际上还没有走得足够远,无法将任何数据发送到服务器。但是,当我在客户端 javascript 中添加行 conn.send ('sending message from the client'); 时,我从 Chrome javascript 控制台收到以下消息:WebSocket {binaryType: "blob", extensions: "", protocol: "", onclose: null, onerror: null...} 未捕获的错误:InvalidStateError:DOM 异常 11 已关闭
  • 那么服务器认为它正在收到一条消息,否则它不会触发 onMessage()。你只是在你的 html 中调用 test_websockets() 来生成上面的 shell 脚本输出吗?
  • 是的,我正在调用 test_websockets()。我已对其进行了更改,以便 conn 变量是全局变量,但这并没有帮助,并且我将对 conn.send() 的调用移至一个单独的 javascript 函数,我可以通过单击 UI 上的 div 来调用该函数。上面的输出显示了来自 OnMessage 的消息,因为我最初试图在创建连接后立即调用 send。但我评论了发送的调用,看看我是否可以先创建连接,但它每次都会关闭。 Firefox 现在告诉我“InvalidStateError:试图使用一个不可用或不再可用的对象”。
  • 您能否更新您的问题以包含所有最新代码?通过 cmets 跟踪您的代码更改非常令人困惑。

标签: php html websocket ratchet


【解决方案1】:

如果您正确遵循 Ratchet 的文档和 RFC6455,那么您会注意到当发出 websocket 连接请求时,将向客户端发送特定响应。除非收到响应,否则客户端将假定尚未建立连接。

您的问题是处理连接的MessageComponentInterface 没有响应连接上的任何套接字响应。但是,Ratchet 与一个已经实现的名为 WsServer 的类捆绑在一起,您的 Chat 类的对象可以传递给该类,并且可以实现所需的操作。不过 WsServer 不是 MessageComponentInterface,但如果你把它包裹在 HttpServer 里面,幸运的是它也与 Ratchet 捆绑在一起,你的问题就会得到解决。

所以您的新代码将如下所示:

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

当然,您需要在命名空间中添加 WsServer 和 HttpServer。

【讨论】:

    【解决方案2】:

    使用

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

    而不是

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

    【讨论】:

      猜你喜欢
      • 2015-08-25
      • 1970-01-01
      • 2017-03-20
      • 2018-10-12
      • 2022-07-30
      • 1970-01-01
      • 2020-04-22
      • 2018-11-09
      • 1970-01-01
      相关资源
      最近更新 更多