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

如何在域名/IP部署WebSocket服务器?生产环境连接失败求助

解决Ratchet WebSocket服务器生产环境无法外部连接及代码问题

一、核心问题:服务器仅监听本地回环地址

你的服务器当前仅监听127.0.0.1:6001,这意味着只有服务器本机可以建立连接,外部请求无法穿透到服务。解决方法是修改Ratchet服务器的监听地址为0.0.0.0(监听所有网卡):

原代码:

$server = new Ratchet\App('localhost', 6001);

修改为:

$server = new Ratchet\App('0.0.0.0', 6001);

修改后重启服务器,执行netstat -tulpn | grep 6001检查,监听地址应显示为0.0.0.0:6001,此时外部即可正常访问。

二、代码中的语法错误

代码存在属性访问语法错误:所有$this->$wclient写法错误,类属性访问不需要在属性名前加$,应改为$this->wclient,否则会触发变量解析异常。

错误示例:

$this->$wclient = new WebSocket\Client("wss://stream-testnet.bybit.com/contract/usdt/public/v3", ['timeout' => 3000]);
$this->$wclient->text($json);

修正后:

$this->wclient = new WebSocket\Client("wss://stream-testnet.bybit.com/contract/usdt/public/v3", ['timeout' => 3000]);
$this->wclient->text($json);

三、Bybit WebSocket连接优化

当前代码在每个客户端onOpen时都创建新的Bybit WebSocket连接,会导致大量重复连接、浪费资源。建议改为类初始化时创建一次共享连接,并处理自动重连逻辑:

class Chat implements MessageComponentInterface {
    protected $clients;
    protected $wclient;

    public function __construct() {
        $this->clients = new \SplObjectStorage;
        // 初始化Bybit连接
        $this->initBybitConnection();
        // 启动异步接收Bybit消息的循环
        $this->startBybitMessageLoop();
    }

    private function initBybitConnection() {
        try {
            $this->wclient = new WebSocket\Client("wss://stream-testnet.bybit.com/contract/usdt/public/v3", ['timeout' => 3000]);
            $subscribeJson = '{"req_id": "100001", "op": "subscribe" ,"args": [
                "orderbook.1.BTCUSDT",
                "orderbook.1.ETHUSDT"
            ]}';
            $this->wclient->text($subscribeJson);
        } catch (\Exception $e) {
            error_log("Bybit连接失败: " . $e->getMessage());
            // 连接失败后延迟重连
            sleep(5);
            $this->initBybitConnection();
        }
    }

    private function startBybitMessageLoop() {
        $loop = \React\EventLoop\Loop::get();
        $loop->addPeriodicTimer(0.001, function() {
            try {
                if ($this->wclient && $message = $this->wclient->receive()) {
                    // 将Bybit推送的消息广播给所有在线客户端
                    foreach ($this->clients as $client) {
                        $client->send($message);
                    }
                }
            } catch (\Exception $e) {
                error_log("Bybit消息接收失败: " . $e->getMessage());
                // 消息接收异常时重新初始化连接
                $this->initBybitConnection();
            }
        });
    }

    public function onOpen(ConnectionInterface $conn) {
        $this->clients->attach($conn);
        echo "新客户端连接: {$conn->resourceId}\n";
    }

    public function onClose(ConnectionInterface $conn) {
        $this->clients->detach($conn);
        echo "客户端断开连接: {$conn->resourceId}\n";
    }

    public function onMessage(ConnectionInterface $from, $data) {
        // 处理客户端发送的消息(按需实现)
        echo "收到客户端{$from->resourceId}消息: {$data}\n";
        $from->send("已收到消息: {$data}");
    }

    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "客户端{$conn->resourceId}错误: {$e->getMessage()}\n";
        $conn->close();
    }
}

$server = new Ratchet\App('0.0.0.0', 6001);
$server->route('/', new Chat, ['*']);
$server->run();

四、验证步骤

  1. 重启修改后的WebSocket服务器:php filename.php
  2. 执行netstat -tulpn | grep 6001确认监听地址为0.0.0.0:6001
  3. 外部客户端重新尝试连接,验证是否成功

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 01:22:06