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

使用Workerman实现WebSocket关闭时发消息及跨连接推送问题

Workerman WebSocket 常见问题解决方案

问题1:onClose回调中调用$connection->send()无效

onClose回调触发时,TCP连接已经完全断开,此时无法再通过$connection->send()向客户端发送数据。如果需要在连接关闭前给客户端发送消息,需在连接尚未关闭的时机处理:

处理方式1:客户端主动关闭时提前发送

当客户端发起关闭请求(比如发送特定指令或WebSocket关闭帧),在onMessage中先发送消息再关闭连接:

private function onMessage($connection, $data) {
    // 假设客户端发送"close"表示请求关闭连接
    if ($data === 'close') {
        // 先发送关闭提示
        $connection->send("连接即将关闭,再见!");
        // 主动关闭连接
        $connection->close();
    }
    // 其他消息逻辑处理
}

处理方式2:服务端主动关闭前发送

如果是服务端主动触发连接关闭,在调用close()方法前先执行send():

// 比如在某个业务逻辑中需要关闭连接
$connection->send("服务端将关闭本次连接");
$connection->close();

问题2:无法向其他连接发送消息

核心原因是没有正确维护所有活跃的连接实例,单进程模式下可通过类属性维护连接池:

步骤1:维护连接池

在类中添加属性存储所有连接,在onConnect时加入,onClose时移除:

// 类属性定义
private $connections = [];

private function onConnect($connection) {
    // 给每个连接分配唯一标识
    $connection->id = uniqid();
    $this->connections[$connection->id] = $connection;
}

private function onClose($connection) {
    // 移除已关闭的连接
    if (isset($this->connections[$connection->id])) {
        unset($this->connections[$connection->id]);
    }
}

步骤2:实现向其他连接发送消息的方法

遍历连接池,排除当前发送者,向其他连接发送消息:

private function broadcastToOthers($fromConn, $message) {
    foreach ($this->connections as $conn) {
        // 跳过消息发送者自身
        if ($conn !== $fromConn) {
            $conn->send($message);
        }
    }
}

调用示例

在onMessage中调用广播方法:

private function onMessage($connection, $data) {
    // 向其他连接广播当前用户的消息
    $this->broadcastToOthers($connection, "其他用户说:{$data}");
}

注意:如果是多进程模式(count > 1),进程间内存不共享,不能用类属性维护连接池,需要借助Redis等外部存储来实现跨进程的连接管理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 05:30:47