webman 本身不内置 websocket 服务,必须搭配 workerman 才能运行;其基于 psr-7/psr-15,生命周期限于单次 http 请求,无法维持长连接,故不能直接 new websocketserver,需通过 workerman worker 独立启动并用 redis 等 ipc 与 webman 协同。

Webman 本身不内置 WebSocket 服务,必须搭配 workerman 扩展才能跑 WebSocket 连接;直接用 Webman 的 HTTP 路由或控制器处理实时推送,数据根本推不出去——连接一断,就只能靠轮询补救。
Webman 项目里为什么不能直接 new WebSocketServer?
Webman 是基于 PSR-7/PSR-15 的 HTTP 框架,它的生命周期绑定在单次请求响应中。WebSocketServer 需要常驻内存、监听 TCP 端口、管理长连接生命周期,而 Webman 的 Worker 进程默认只处理 HTTP 请求,不维持 socket 连接状态。
- 你如果在
controller里尝试new WebSocketServer('websocket://0.0.0.0:2346'),会报Class 'WebSocketServer' not found或直接阻塞进程——因为没引入 workerman 的启动机制 - Webman 的
onWorkerStart回调里也不能直接起 server,必须通过Workerman\Worker实例注册并交由 workerman 主循环接管 - 常见错误现象:
Connection refused(端口没真正监听)、前端WebSocket connection to 'ws://...' failed(握手 400 或超时),基本都源于 server 没被 workerman 正确加载
如何让 Webman 和 WebSocket 共存于同一项目?
核心是「分工」:Webman 处理静态资源、API 接口、登录鉴权等 HTTP 逻辑;WebSocket 服务由独立的 workerman 进程承载,两者通过 PHP 进程间通信(如 Redis、Unix Socket 或共享内存)交换数据。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 在
process/目录下新建websocket_process.php,用Workerman\Worker启动websocket://0.0.0.0:2346 - Webman 的业务逻辑(比如管理员点击“推送全屏”)调用
Redis::publish('screen:topic', $data) -
websocket_process.php中用Redis::subscribe()监听该 channel,收到后调用$connection->send()广播给所有在线客户端 - 不要把 Webman 的容器实例(如
Container)传进 WebSocket 进程回调里——它不是线程安全的,会引发Serialization of 'Closure' is not allowed
前端连上 ws 后收不到数据?检查这三处
WebSocket 连接成功只是第一步,90% 的“收不到推送”问题出在服务端广播逻辑或客户端订阅机制上。
- 服务端是否真的在向正确的
Session发送?workerman的$worker->connections是全部连接,但你要推送给“大屏专用连接”,就得加标识——比如握手时 URL 带?type=dashboard,然后在onConnect里存入$connection->type = 'dashboard' - 前端是否绑定了正确的事件?别只写
ws.onmessage,要确认服务端发的是字符串还是 JSON:JSON.parse(event.data)会因格式错直接静默失败 - 跨域或路径写错?
ws://localhost:8787和wss://yourdomain.com是完全不同的 origin,浏览器会拦截;Nginx 反向代理 WebSocket 时,必须显式配置Upgrade和Connection头,否则握手降级成 HTTP
真正难的不是连上 WebSocket,而是让每一次 send() 都精准落到目标设备——尤其是当大屏和手机端共用一个连接池时,漏发、错发、重复发,全藏在连接标识和广播条件判断里。










