You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Symfony 6+Ratchet开发实时聊天:WebSocket本地连接失败求助

问题:Symfony 6 + Ratchet 无法建立WebSocket连接

使用Symfony 6、Ratchet与JavaScript开发实时聊天功能,控制台显示连接URL(wss://localhost:8000/game)无误,但始终无法建立WebSocket连接。相关代码如下:

命令类代码

<?php

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

use Ratchet\App;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use App\Websocket\MessageHandler;

use App\Sockets\LiveChat;


class SocketCommand extends Command
{
    protected function configure()
    {
        $this->setName('sockets:start-chat')
            ->setHelp("Starts the chat socket demo")
            ->setDescription('Starts the chat socket demo');
    }

    protected function execute(InputInterface $input, OutputInterface $output)
    {

        // $server = IoServer::factory(
        //     new HttpServer(
        //         new WsServer(
        //             new LiveChat()
        //         )
        //     ),
        //     8000
        // );
        $output->writeln([
            'Chat socket',
            '============',
            'Starting chat, open your browser.',
        ]);
        //$app = new App('localhost', 8000, '127.0.0.1');
        $app = new \Ratchet\App('127.0.0.1', 8000, '0.0.0.0');
        $app->route('/game', new LiveChat);
        $app->run();
    }
}

WebSocket初始化类代码

<?php

namespace App\Sockets;

use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use SplObjectStorage;

class LiveChat implements MessageComponentInterface
{
    protected $clients;

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

    public function onOpen(ConnectionInterface $conn)
    {
        $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();
    }
}

前端JavaScript代码

var clientInformation = {
    username: new Date().getTime().toString()
        // You can add more information in a static object
};

var conn = new WebSocket('ws://localhost:8000/game');

console.log(conn);

conn.onopen = function(e) {
    console.info("Connection established succesfully");
};

conn.onmessage = function(e) {
    var data = JSON.parse(e.data);
    Chat.appendMessage(data.username, data.message);

    console.log(data);
};

conn.onerror = function(e) {
    alert("Error: something went wrong with the socket.");
    console.error(e);
};

document.getElementById("form-submit").addEventListener("click", function() {
    var msg = document.getElementById("form-message").value;

    if (!msg) {
        alert("Please send something on the chat");
    }

    Chat.sendMessage(msg);

    document.getElementById("form-message").value = "";
}, false);

var Chat = {
    appendMessage: function(username, message) {
        var from;

        if (username == clientInformation.username) {
            from = "me";
        } else {
            from = clientInformation.username;
        }

        var ul = document.getElementById("chat-list");
        var li = document.createElement("li");
        li.appendChild(document.createTextNode(from + " : " + message));
        ul.appendChild(li);
    },
    sendMessage: function(text) {
        clientInformation.message = text;
        conn.send(JSON.stringify(clientInformation));
        this.appendMessage(clientInformation.username, clientInformation.message);
    }
};

解决要点

  • 协议不匹配:后端未配置SSL证书,前端不能用wss://,需改为ws://localhost:8000/game。
  • 语法错误:LiveChat类的onError方法中有多余字符w,已在代码中修正,否则会导致Socket服务启动失败。
  • 端口冲突:如果Symfony默认使用8000端口,需修改Symfony启动端口,比如执行symfony server:start --port=8001,避免与Socket服务的8000端口冲突。
  • 确保Socket服务运行:必须保持php bin/console sockets:start-chat命令处于运行状态,关闭终端会终止服务。
  • 跨域检查:Ratchet的App类默认处理跨域,若仍有问题,可在创建App实例时添加跨域配置,或在前端使用代理。

内容的提问来源于stack exchange,提问作者Ethan Clement

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 18:31:09