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

使用Workerman从后端PHP脚本向WebSocket客户端发消息失败排查

排查步骤与解决方案

1. 确认HTTP Worker是否正常启动并监听

  • 检查server.php中HTTP Worker的初始化代码,确保端口、协议正确,且与WebSocket Worker一同启动:
    $http_worker = new Worker('http://0.0.0.0:8081');
    $http_worker->count = 1; // 根据需求设置进程数
    // 临时添加日志,验证事件是否触发
    $http_worker->onMessage = function($conn, $data) {
        file_put_contents('http_worker.log', date('Y-m-d H:i:s') . ' 收到请求: ' . $data . PHP_EOL, FILE_APPEND);
        // 后续发送逻辑
    };
    
    $ws_worker = new Worker('websocket://0.0.0.0:8080');
    // WebSocket相关逻辑...
    
    Worker::runAll(); // 必须调用,启动所有Worker
    
  • 启动服务后,执行ps aux | grep workerman查看进程,确认HTTP Worker进程存在。

2. 验证CURL请求是否到达HTTP Worker

  • 执行CURL请求后,查看http_worker.log是否有日志写入:
    • 若无日志:检查CURL请求的目标IP/端口是否与HTTP Worker监听一致;排查防火墙/端口占用问题;添加var_dump(curl_error($ch))查看CURL报错信息。
    • 有日志:说明HTTP Worker已收到请求,问题出在后续消息发送逻辑。

3. 解决WebSocket连接的跨进程访问问题

Workerman不同Worker进程的内存相互隔离,若HTTP Worker与WebSocket Worker为不同进程,直接遍历WebSocket Worker的$worker->connections或全局数组会为空,需用Channel组件实现进程间通信:

  1. 安装Channel组件:composer require workerman/channel
  2. 在server.php中启动Channel服务:
    use Workerman\Channel\Server;
    // 启动Channel服务,端口可自定义
    new Server('0.0.0.0', 2206);
    
  3. WebSocket Worker订阅广播频道:
    $ws_worker->onWorkerStart = function($worker) {
        \Workerman\Channel\Client::connect('127.0.0.1', 2206);
        // 收到频道消息时广播给所有WebSocket客户端
        \Workerman\Channel\Client::on('broadcast', function($msg) use($worker) {
            foreach($worker->connections as $conn) {
                // 检查连接状态是否正常
                if($conn->status == \Workerman\Connection\TcpConnection::STATUS_ESTABLISHED) {
                    $conn->send($msg);
                }
            }
        });
    };
    
  4. HTTP Worker发布消息到频道:
    $http_worker->onMessage = function($conn, $data) {
        // 解析请求数据(以POST表单为例)
        parse_str($data, $post);
        $msg = $post['msg'] ?? '';
        if(empty($msg)) {
            $conn->send('false');
            return;
        }
        // 连接Channel并发布消息
        \Workerman\Channel\Client::connect('127.0.0.1', 2206);
        \Workerman\Channel\Client::publish('broadcast', $msg);
        $conn->send('true');
    };
    

4. 检查消息发送逻辑的正确性

  • 若使用单进程模式,确认WebSocket连接是否被正确存储与清理:
    // WebSocket Worker的onConnect事件
    $ws_worker->onConnect = function($conn) {
        global $ws_connections;
        $ws_connections[$conn->id] = $conn;
    };
    // onClose事件移除无效连接
    $ws_worker->onClose = function($conn) {
        global $ws_connections;
        unset($ws_connections[$conn->id]);
    };
    
  • 发送消息时务必检查连接状态:
    foreach($ws_connections as $conn) {
        if($conn->status == \Workerman\Connection\TcpConnection::STATUS_ESTABLISHED) {
            $conn->send($msg);
        }
    }
    

5. 验证CURL请求格式

确保CURL发送的数据格式与HTTP Worker解析逻辑匹配:

  • POST表单格式的CURL示例:
    $ch = curl_init('http://127.0.0.1:8081');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['msg' => '后端推送消息']));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $result = curl_exec($ch);
    // 检查CURL错误
    if(curl_errno($ch)) {
        echo 'CURL错误: ' . curl_error($ch);
    }
    curl_close($ch);
    
  • JSON格式的CURL示例:
    $ch = curl_init('http://127.0.0.1:8081');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['msg' => '后端推送消息']));
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $result = curl_exec($ch);
    // HTTP Worker中解析:$data = json_decode($data, true);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 01:35:16