如何在CodeIgniter中实现WebSocket与Android双向通信及Webhook推送?
Android与CodeIgniter服务端非轮询双向通信最优方案
针对你的场景,WebSocket是最优实现方案——它原生支持双向实时通信,无需额外中间件(相比MQTT),也避免了轮询的资源浪费与延迟问题,完全适配你需要的"服务端主动推送webhook数据到Android客户端"的需求。
具体实现方案
1. CodeIgniter服务端实现(WebSocket + Webhook处理)
PHP本身对WebSocket支持有限,推荐使用成熟的Ratchet库搭建WebSocket服务,同时配合CodeIgniter处理webhook回调:
步骤1:安装Ratchet
通过Composer安装:
composer require cboden/ratchet
步骤2:创建WebSocket服务类
在CodeIgniter的application/libraries下创建WebSocketServer.php,处理连接、消息、断开事件,同时维护客户端标识与连接的映射:
<?php use Ratchet\MessageComponentInterface; use Ratchet\ConnectionInterface; class WebSocketServer implements MessageComponentInterface { protected $clients; protected $clientMap; // 存储标识(如设备ID/请求ID)与连接的映射 public function __construct() { $this->clients = new \SplObjectStorage; $this->clientMap = []; } public function onOpen(ConnectionInterface $conn) { $this->clients->attach($conn); // Android连接时会发送标识(如设备ID),后续在onMessage中处理映射 } public function onMessage(ConnectionInterface $from, $msg) { $data = json_decode($msg, true); // 存储标识与连接的映射,比如用请求ID或者设备ID if(isset($data['client_id'])) { $this->clientMap[$data['client_id']] = $from; } // 处理Android发送的初始消息,调用第三方API // ... 这里写调用第三方API的逻辑,记录请求ID与client_id的关联 } public function onClose(ConnectionInterface $conn) { $this->clients->detach($conn); // 移除clientMap中的对应条目 foreach($this->clientMap as $id => $connection) { if($connection === $conn) { unset($this->clientMap[$id]); break; } } } public function onError(ConnectionInterface $conn, \Exception $e) { $conn->close(); } // 提供给webhook控制器调用的推送方法 public function pushToClient($clientId, $data) { if(isset($this->clientMap[$clientId])) { $this->clientMap[$clientId]->send(json_encode($data)); } } }
步骤3:启动WebSocket服务
在CodeIgniter根目录创建start-websocket.php:
<?php use Ratchet\Server\IoServer; use Ratchet\Http\HttpServer; use Ratchet\WebSocket\WsServer; require 'vendor/autoload.php'; require 'application/libraries/WebSocketServer.php'; $server = IoServer::factory( new HttpServer( new WsServer( new WebSocketServer() ) ), 8080 // 自定义WebSocket端口 ); $server->run();
启动服务:php start-websocket.php
步骤4:Webhook回调处理
在CodeIgniter中创建Webhook控制器,收到第三方响应后,调用WebSocket服务的推送方法:
<?php defined('BASEPATH') OR exit('No direct script access allowed'); class Webhook extends CI_Controller { public function callback() { $webhookData = json_decode(file_get_contents('php://input'), true); // 从webhook数据中获取之前记录的client_id(比如第三方返回的请求ID对应我们存储的client_id) $clientId = $this->getClientIdByRequestId($webhookData['request_id']); // 获取WebSocket服务实例并推送数据 $wsServer = new WebSocketServer(); $wsServer->pushToClient($clientId, $webhookData); echo json_encode(['status' => 'success']); } private function getClientIdByRequestId($requestId) { // 从数据库/缓存中取出之前Android请求时记录的request_id与client_id的关联 // ... 实现逻辑 } }
2. Android客户端实现(OkHttp WebSocket)
使用OkHttp库实现WebSocket客户端,建立连接、发送初始消息、监听服务端推送:
步骤1:添加OkHttp依赖
在build.gradle中添加:
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
步骤2:WebSocket客户端代码示例
import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.WebSocket; import okhttp3.WebSocketListener; import okio.ByteString; public class MyWebSocketClient extends WebSocketListener { private WebSocket webSocket; private String clientId = "设备唯一标识或用户ID"; public void connect() { OkHttpClient client = new OkHttpClient.Builder() .build(); Request request = new Request.Builder() .url("ws://你的服务端IP:8080") .build(); webSocket = client.newWebSocket(request, this); } // 发送初始消息到服务端 public void sendInitialMessage(String requestData) { String jsonMsg = "{\"client_id\":\"" + clientId + "\",\"data\":\"" + requestData + "\"}"; webSocket.send(jsonMsg); } @Override public void onOpen(WebSocket webSocket, okhttp3.Response response) { // 连接成功,发送初始消息 sendInitialMessage("Android客户端的请求数据"); } @Override public void onMessage(WebSocket webSocket, String text) { // 收到服务端推送的webhook数据,处理逻辑 handleWebhookData(text); } @Override public void onMessage(WebSocket webSocket, ByteString bytes) { // 处理二进制消息(可选) } @Override public void onClosing(WebSocket webSocket, int code, String reason) { webSocket.close(1000, null); } @Override public void onFailure(WebSocket webSocket, Throwable t, okhttp3.Response response) { // 连接失败,实现重连逻辑 reconnect(); } private void handleWebhookData(String data) { // 解析并处理服务端推送的webhook数据 } private void reconnect() { // 实现指数退避重连逻辑,避免频繁重试 } }
方案优势对比
- 对比MQTT:无需部署额外的MQTT broker(如Mosquitto),架构更轻量化,与CodeIgniter服务端集成更直接,减少运维成本。
- 对比轮询:完全消除无效请求,实时性接近毫秒级,大幅降低服务端与客户端的资源消耗。
注意事项
- 连接保活:WebSocket默认有心跳机制,也可以自定义心跳包避免连接被网关断开。
- 断线重连:Android客户端需实现重连逻辑,结合指数退避策略避免频繁重试。
- 连接映射存储:如果服务端需要多进程部署,建议用Redis存储client_id与连接标识的映射(Ratchet的连接对象无法跨进程共享),webhook回调时从Redis获取对应连接标识,再推送数据。
内容的提问来源于stack exchange,提问作者Shubham Agrawal
相关产品推荐
相关产品推荐

