跳转到主内容
极星编程网:以代码为星,赴技术山海!

CodeIgniter如何实现即时通讯_CodeIgniterWebsocket应用示例【即时】

CodeIgniter 3.x 不支持 WebSocket,因控制器依赖 PHP-FPM 生命周期,而 WebSocket 需常驻进程;必须用 Ratchet 独立启动 CLI 服务,通过 Redis 共享状态并手动管理连接与鉴权。 CodeIgniter 3.x 本身不支持 WebSocket,任何试图在
Chat.php
控制器里写
onOpen()
或直接
new WsServer
的做法都会失败——连接握手后几秒内必然断开,
onMessage()
永远不会触发。 为什么不能在 CI 控制器里启动 WebSocket 服务 WebSocket 握手虽用 HTTP GET +
Upgrade: websocket
头发起,但后续通信完全脱离 PHP-FPM 生命周期。CI 的控制器由 Apache/Nginx 调用,请求一结束,整个进程(含所有对象实例)即被销毁。
ConnectionInterface
实例随之消失,Ratchet 的事件循环根本无法持续运行。 常见错误现象: 浏览器控制台显示
WebSocket connection to 'ws://localhost:8080/' failed
服务端日志刷出
New connection! (123)
,但无后续
onMessage
日志 用
ps aux | grep php
查不到常驻的
chat_server.php
进程 必须用 Ratchet 启动独立常驻进程 Ratchet 不是 CI 插件,而是一个独立的 PHP WebSocket 服务框架。它需绕过 CI 入口(
index.php
),用 CLI 方式长期运行,与 CI 应用并行,仅通过共享存储交换数据。 实操要点: 在项目根目录新建
chat_server.php
,不放在
application/
下 用原生 PDO 或
new Redis()
连接数据库/缓存, 不要调用
$this->ci->load->model()
(
get_instance()
在 CLI 环境下返回
null
) 启动命令必须带
php
前缀:
php chat_server.php
,不能用
php -S
(那是内置 HTTP 服务器) 绑定地址建议用
0.0.0.0:8080
而非
127.0.0.1:8080
,避免 Docker 或跨域调试时连不上 CI 与 Ratchet 如何共享用户身份和在线状态 二者没有内存或会话共享,必须设计轻量级状态同步机制。推荐用 Redis 存储临时 token 映射,比查数据库更快也更可靠。 WebSocket 8.18.2 WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。 下载 关键步骤: 用户登录成功后,CI 写入:
SET ws:token:abc123 "{"user_id":5,"expires":1747000000}"
,并设 TTL(如 3600 秒) Ratchet 在
onOpen()
中解析 URL 参数
?token=abc123
,用
$redis->get('ws:token:abc123')
获取用户 ID 验证通过后,将
$conn->resourceId
与
user_id
写入 Redis Hash:
HSET ws:online 123 5
广播消息前,先
HVALS ws:online
拿到所有在线
user_id
,再查表得对应
resourceId
列表,逐个
$conn->send()
前端连接与鉴权不能依赖 CI Session 浏览器 WebSocket 连接(
new WebSocket('ws://...?token=...')
)发生在 HTTP 请求之外,
$_SESSION
和 CI 的
$this->session
完全不可见。任何基于 Cookie 的自动鉴权都无效。 必须显式传递凭证: 登录接口返回一个短期有效的
token
字段(非 session_id),前端存入
localStorage
建立 WebSocket 连接时手动拼 URL:
new WebSocket('ws://localhost:8080?token=' + token)
Ratchet 端不做信任假设:每个
onMessage
都要校验该
resourceId
是否仍存在于
ws:online
中,防止伪造连接 ID 前端收到
close
事件后,主动清除本地 token 缓存,避免重连时用失效凭证 最易被忽略的是:Ratchet 进程里所有数据库/缓存操作都必须自己初始化,CI 的自动加载、配置、钩子全部失效;一旦你写了
$this->db->insert()
或
$this->redis->lPush()
,就等于默认它已存在——而这在 CLI 环境下从来不会自动发生。

相关文章