workerman主动推送收不到的根源是连接静默断开未被感知,需依次检查established连接数、onmessage日志、tcpdump抓包验证半关闭状态,确认uid绑定有效、心跳检测启用及推送通道配置一致。

Workerman主动推送信息突然收不到,说明服务端已发、客户端却未收到,常见于连接状态异常但未被及时感知的场景——比如用户页面刷新后旧连接未断开,新连接未绑定UID,导致消息被发到已失效的连接上。
检查连接是否真实存活
第一步:用 netstat -an | grep :端口号 查看服务端监听端口是否有 ESTABLISHED 连接;若数量远低于在线用户数,说明大量连接已静默断开但未触发 onClose 回调。
第二步:在 onMessage 中加日志,记录每次收到消息的 $connection->id 和 $connection->getRemoteIp();若某 IP 长时间无新连接 ID 出现,大概率是前端未重连或重连后未发送初始化 bind 指令。
第三步:手动触发一次推送,同时用 tcpdump -i any port 端口号 抓包;如果服务端有 send() 调用但抓不到对应 TCP 数据包,说明连接已处于半关闭状态(FIN 已发但未 ACK),Workerman 仍将其保留在 $worker->connections 数组中——【这是最隐蔽的“收不到”根源】。
验证 UID 绑定是否生效
方法一:在推送前插入调试逻辑:var_dump(Gateway::getClientCountByUid($uid));。返回 0 就代表该 UID 当前无任何有效连接,推送必然失败。
方法二:检查前端是否在 WebSocket 连接建立后,立即发送了 {"type":"init","id":123} 类型的消息。漏掉这一步,Gateway 就不会执行 Gateway::bindUid($client_id, $uid),后续所有 sendToUid 都无效。
一款AI图像与设计工具,主要用于一款加速产品 UI 设计迭代的工具,可以一键将任意网页和交互导入到 Pixso、MasterGo、即时设计、Figma,实现像素级还原,适合需要提升相关任务效率的用户。
注意:如果用户多设备登录,bindUid 默认会覆盖旧连接。若业务需要保留全部设备,必须在 Events.php 的 onConnect 里改用 addConnection 手动维护映射表,否则旧手机上的连接会被新平板的绑定挤掉。
排查心跳机制是否失效
打开浏览器开发者工具 → Network → 过滤 ws,观察 WebSocket 连接的 Frames 标签页。正常应每 30 秒左右出现一条 ping 或 pong 帧。如果连续 2 分钟没帧交互,NAT 网关大概率已切断连接,但 Workerman 还以为它活着。
此时必须在 onWorkerStart 中启动定时心跳检测:Timer::add(25, function () { Gateway::checkClientConnection(); });。不加这句,Gateway::sendToUid 会把消息发给一堆“僵尸连接”。
这一步操作起来很简单,直接把定时器加进启动逻辑就行,但漏掉就会让推送成功率断崖式下跌。
确认推送指令是否命中正确通道
推送时务必核对协议和端口是否与前端连接一致:前端连的是 ws://domain.com:8282,后端推送就必须用 Gateway::sendToUid($uid, $msg);若前端实际连的是 wss://domain.com:443(反向代理后),而 Gateway 配置仍是 tcp://0.0.0.0:8282,则根本不在同一通信平面。
查配置文件里的 GATEWAY_WORKER_PORT 和 REGISTER_ADDRESS 是否与启动脚本中的监听地址完全匹配。哪怕只差一个点(如 127.0.0.1 vs 0.0.0.0),都会导致内部路由失败。










