当前位置:首页 > PHP

php 实现长轮询

2026-02-13 16:47:29PHP

PHP 实现长轮询的方法

长轮询(Long Polling)是一种服务器推送技术,客户端向服务器发送请求后,服务器保持连接开放,直到有数据可发送或超时。以下是实现长轮询的步骤和代码示例。

服务器端代码

创建一个 PHP 脚本(如 long_polling.php)处理长轮询请求。该脚本会检查数据更新,并在有更新或超时时返回响应。

<?php
// 设置脚本执行时间不受限制
set_time_limit(0);

// 模拟数据存储(实际应用中可能使用数据库或缓存)
$lastUpdate = isset($_GET['lastUpdate']) ? (int)$_GET['lastUpdate'] : 0;

// 长轮询超时时间(秒)
$timeout = 30;
$startTime = time();

// 检查数据是否更新
while (true) {
    // 模拟数据更新(实际应用中根据业务逻辑判断)
    $currentUpdate = filemtime('data.txt'); // 假设通过文件修改时间判断更新

    if ($currentUpdate > $lastUpdate) {
        // 返回新数据
        $response = [
            'status' => 'success',
            'data' => file_get_contents('data.txt'),
            'lastUpdate' => $currentUpdate
        ];
        echo json_encode($response);
        break;
    }

    // 检查是否超时
    if (time() - $startTime >= $timeout) {
        $response = ['status' => 'timeout'];
        echo json_encode($response);
        break;
    }

    // 减少 CPU 占用
    usleep(100000); // 0.1 秒
}
?>

客户端代码

使用 JavaScript 发起长轮询请求,并在收到响应后处理数据或重新发起请求。

function longPolling(lastUpdate = 0) {
    fetch(`long_polling.php?lastUpdate=${lastUpdate}`)
        .then(response => response.json())
        .then(data => {
            if (data.status === 'success') {
                console.log('New data:', data.data);
                // 处理新数据后继续轮询
                longPolling(data.lastUpdate);
            } else if (data.status === 'timeout') {
                // 超时后重新发起轮询
                longPolling(lastUpdate);
            }
        })
        .catch(error => {
            console.error('Polling error:', error);
            // 错误后重新发起轮询
            setTimeout(() => longPolling(lastUpdate), 1000);
        });
}

// 启动长轮询
longPolling();

实际应用优化

  • 数据存储:替换文件操作为数据库或缓存(如 Redis),通过查询判断数据更新。
  • 性能优化:避免频繁查询数据库,可以使用缓存或消息队列。
  • 错误处理:增加客户端重试机制和服务器端日志记录。
  • 安全性:验证客户端请求,防止恶意攻击。

示例:数据库实现

假设使用 MySQL 存储数据,通过检查 last_modified 字段判断更新:

php 实现长轮询

<?php
set_time_limit(0);
$lastUpdate = isset($_GET['lastUpdate']) ? (int)$_GET['lastUpdate'] : 0;
$timeout = 30;
$startTime = time();

// 数据库连接
$db = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');

while (true) {
    $stmt = $db->prepare("SELECT * FROM messages WHERE last_modified > ? LIMIT 1");
    $stmt->execute([$lastUpdate]);
    $data = $stmt->fetch(PDO::FETCH_ASSOC);

    if ($data) {
        echo json_encode([
            'status' => 'success',
            'data' => $data['content'],
            'lastUpdate' => $data['last_modified']
        ]);
        break;
    }

    if (time() - $startTime >= $timeout) {
        echo json_encode(['status' => 'timeout']);
        break;
    }

    usleep(100000);
}
?>

通过以上方法,可以实现高效的长轮询机制,适用于实时性要求较高的应用场景。

标签: php长轮询
分享给朋友:

相关文章

php实现分页

php实现分页

PHP实现分页的基本方法 使用原生PHP实现分页功能需要结合数据库查询和HTML展示。以下是核心实现步骤: 数据库查询与分页逻辑 // 连接数据库 $conn = new mysqli('loca…

php 实现自动收货

php 实现自动收货

PHP 实现自动收货功能 自动收货功能通常用于电商系统,在订单超过一定时间未手动确认收货时自动完成订单。以下是实现方法: 数据库设计 需要订单表包含以下关键字段: CREATE TABLE…

php实现接口

php实现接口

PHP 实现接口的方法 在 PHP 中,接口(Interface)用于定义一组方法的规范,而不实现具体功能。类可以实现一个或多个接口,并必须实现接口中定义的所有方法。 定义接口 接口使用 inter…

php搜索功能实现

php搜索功能实现

实现基本的PHP搜索功能 使用MySQL数据库和PHP实现简单的关键词搜索功能。需要确保数据库中有可供搜索的表和数据。 // 连接数据库 $conn = new mysqli('localhost'…

php 实现类

php 实现类

PHP 类的基本实现 在 PHP 中,类通过 class 关键字定义,后跟类名和一对花括号。类名通常遵循大驼峰命名法(如 ClassName)。以下是基本语法: class ClassName {…

php 实现单点登录

php 实现单点登录

PHP 实现单点登录的方法 单点登录(SSO)允许用户通过一次登录访问多个相互信任的系统。以下是基于 PHP 的实现方案: 基于共享 Session 的方案 在同一个主域名下的子域名间可以通过共享…