$connection->send()是唯一可靠直接的发送方式,适用于一对一消息;广播需遍历$worker->connections并检查连接状态;跨进程需用gatewayworker并确保register进程运行。

$connection->send() 是唯一可靠、直接、无需额外组件的发送方式。其他方法(如 GatewayWorker::sendToClient() 或广播到 $worker->connections)本质也依赖它,但适用场景不同,用错会丢消息或报错。
直接调用 $connection->send() 发送单条消息
这是最基础也最常用的发送方式,适用于响应客户端请求、回传处理结果等一对一场景。
-
$data必须是字符串或可序列化为字符串的内容(如json_encode($arr)),不能直接传数组或对象 - 发送前建议检查连接状态:
if ($connection->connected),否则可能触发 warning 或静默失败 - 二进制数据需显式标记:
$connection->send($binary_data, true),第二个参数设为true表示 binary 类型 - 如果
$data含非 UTF-8 字符(如 GBK 编码的中文),浏览器 WebSocket 会关闭连接 —— 务必确保mb_convert_encoding($data, 'UTF-8', 'auto')
向所有在线客户端广播:遍历 $worker->connections
适合聊天室、通知公告等群发场景,但要注意连接有效性与并发安全。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 必须在
$ws_worker->onMessage或其它 worker 上下文中使用,$ws_worker是创建时的变量名,不是全局对象 - 不能直接 foreach
$ws_worker->connections并 send —— 某些连接可能已断开但尚未被 Workerman 清理,需加if ($conn->connected)判断 - 高并发下频繁遍历全部连接会影响性能;连接数超 5000 时建议改用
GatewayWorker的sendToAll() - 注意:该方式无法跨进程广播(Workerman 多进程间不共享内存),
$worker->connections仅包含当前进程内的连接
用 GatewayWorker 实现跨进程/分布式广播
当需要稳定支持万级连接、私聊、房间、离线消息时,GatewayWorker 不是“高级选项”,而是必要架构。
-
GatewayWorker::sendToClient($client_id, $data)和GatewayWorker::sendToAll($data)是线程安全的,底层走 register 服务协调 - 必须先启动
Register进程(监听127.0.0.1:1236),否则sendToClient会返回 false 且无日志提示 -
$client_id需由客户端在连接后主动上报(例如登录成功时发{"type":"login","user_id":123}),服务端存入$connection->id = $user_id - 不要在
onConnect回调里直接调用sendToClient—— 此时$connection->id尚未注册到 Gateway,会失败
常见发送失败原因和排查点
消息发不出去,90% 不是代码写错,而是环境或逻辑卡点没注意到。
- 前端 WebSocket 连接状态是
readyState === 1才能收消息;若为0(connecting)或2/3(closing/closed),send()无效 - Workerman 进程被 kill 或异常退出后,
onMessage不再触发 —— 用php start.php status确认 worker 是否仍在运行 - 防火墙或 Nginx 反代未透传 WebSocket 升级头(
Upgrade: websocket、Connection: Upgrade),导致握手失败,后续所有send都无意义 - PHP 输出了非 WebSocket 协议内容(如
echo "debug"或错误警告)到 socket,会破坏帧格式,浏览器立即断连









