You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 18:27:44