必须在推送前确认客户端连接活跃,否则会触发警告或内存泄漏;通过$connection->isConnected()判断连接状态,结合心跳时间戳校验失活情况,并用Gateway::isOnline()检测在线状态,同时在onClose事件中清理映射表以避免内存膨胀。

要确保Workerman主动推送信息时不把消息发给已断开的客户端,必须在推送前确认目标连接仍处于活跃状态,否则会触发PHP Warning或导致内存泄漏。
通过connection->isConnected()判断连接有效性
在Worker实例中,每个客户端连接对象都提供isConnected()方法,返回布尔值。
直接调用$connection->isConnected()即可获知该连接是否仍可通信,这是最轻量、最可靠的判断方式。
若返回false,说明TCP连接已关闭(无论主动断开还是网络中断),此时调用$connection->send()会抛出异常并可能使进程崩溃。
结合心跳时间戳做双重校验
仅靠isConnected()不够——某些场景下连接未关闭但客户端已失活(如手机锁屏、浏览器标签页休眠),需配合心跳机制。
第一步:在onMessage中持续更新连接的心跳时间戳
例如:$connection->lastHeartbeat = time();
第二步:推送前检查时间差是否超限
例如:if (time() - $connection->lastHeartbeat > 60) { return false; }
【必须在onMessage中设置lastHeartbeat,否则该属性不存在】
第三步:同时验证isConnected()与时间戳,两者都通过才执行send()
使用GatewayWorker时通过Gateway::isOnline()检测
方法一:直接查在线状态
调用Gateway::isOnline($client_id),返回true表示客户端当前在线且可收消息。
方法二:批量推送前过滤离线ID
若你持有用户UID列表,可用Gateway::getClientIdByUid($uid)获取client_id,再逐个isOnline()校验。
注意:Gateway::isOnline()底层已封装了连接存活检测和超时逻辑,比手动维护时间戳更稳妥。
这一步操作起来很简单,直接把client_id传进去就行。
监听onClose事件清理连接映射表
第一步:在Worker或BusinessWorker的onClose回调中,从自定义映射数组(如$worker->uidConnections)里unset对应项
第二步:推送前先查映射表是否存在该uid或client_id,不存在则跳过
第三步:若存在,再调用isConnected()或isOnline()做最终确认
没有这步清理,映射表会不断膨胀,长期运行后内存占用飙升,且推送总失败。
【映射表不清理会导致推送目标永远无法被识别为离线】

















