PHP 怎么PHP Web推送

wen PHP项目 1

本文目录导读:

PHP 怎么PHP Web推送

  1. Server-Sent Events (SSE) 实现
  2. WebSocket 实现
  3. 使用第三方推送服务
  4. 选择建议
  5. 生产环境注意事项

我将为您详细介绍 PHP Web 推送的几种实现方式,主要包括Server-Sent Events (SSE)WebSocket 两种技术方案。

Server-Sent Events (SSE) 实现

SSE 是单向推送(服务器→客户端),实现简单,适合消息推送、通知等场景。

服务器端代码 (push.php)

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('Access-Control-Allow-Origin: *');
// 设置无限执行时间
set_time_limit(0);
ob_implicit_flush(true);
ob_end_flush();
// 模拟数据推送
$counter = 0;
while (true) {
    $counter++;
    // 发送事件数据
    echo "id: {$counter}\n";
    echo "event: message\n";
    echo "data: " . json_encode([
        'time' => date('Y-m-d H:i:s'),
        'message' => "这是第 {$counter} 条消息"
    ]) . "\n\n";
    // 检查客户端是否断开连接
    if (connection_aborted()) {
        break;
    }
    sleep(2);
}

客户端 JavaScript 代码

<!DOCTYPE html>
<html>
<head>SSE 示例</title>
</head>
<body>
    <div id="messages"></div>
    <script>
    // 创建 EventSource 连接
    const eventSource = new EventSource('push.php');
    // 监听消息事件
    eventSource.addEventListener('message', function(e) {
        const data = JSON.parse(e.data);
        const messagesDiv = document.getElementById('messages');
        messagesDiv.innerHTML += `<p>${data.time}: ${data.message}</p>`;
    });
    // 监听连接打开
    eventSource.addEventListener('open', function(e) {
        console.log('连接已建立');
    });
    // 监听错误
    eventSource.addEventListener('error', function(e) {
        console.error('连接错误:', e);
        eventSource.close();
    });
    </script>
</body>
</html>

WebSocket 实现

WebSocket 支持双向通信,适合实时交互场景,需要安装 RatchetSwoole 等库。

使用 Ratchet(推荐)

安装 Ratchet

composer require cboden/ratchet

服务器端代码 (server.php)

<?php
require 'vendor/autoload.php';
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
class WebSocketServer implements MessageComponentInterface {
    protected $clients;
    public function __construct() {
        $this->clients = new \SplObjectStorage;
    }
    public function onOpen(ConnectionInterface $conn) {
        // 存储新连接
        $this->clients->attach($conn);
        echo "新连接: {$conn->resourceId}\n";
        // 发送欢迎消息
        $conn->send(json_encode([
            'type' => 'welcome',
            'message' => '欢迎连接 WebSocket 服务器'
        ]));
    }
    public function onMessage(ConnectionInterface $from, $msg) {
        $data = json_decode($msg, true);
        switch ($data['type']) {
            case 'broadcast':
                // 广播消息给所有客户端
                foreach ($this->clients as $client) {
                    if ($from !== $client) {
                        $client->send(json_encode([
                            'type' => 'broadcast',
                            'from' => $from->resourceId,
                            'message' => $data['message']
                        ]));
                    }
                }
                break;
            case 'private':
                // 发送私信给指定客户端
                $targetId = $data['target'];
                foreach ($this->clients as $client) {
                    if ($client->resourceId == $targetId) {
                        $client->send(json_encode([
                            'type' => 'private',
                            'from' => $from->resourceId,
                            'message' => $data['message']
                        ]));
                        break;
                    }
                }
                break;
        }
    }
    public function onClose(ConnectionInterface $conn) {
        $this->clients->detach($conn);
        echo "连接关闭: {$conn->resourceId}\n";
    }
    public function onError(ConnectionInterface $conn, \Exception $e) {
        echo "错误: {$e->getMessage()}\n";
        $conn->close();
    }
}
// 创建 WebSocket 服务器
$server = IoServer::factory(
    new HttpServer(
        new WsServer(
            new WebSocketServer()
        )
    ),
    8080
);
echo "WebSocket 服务器启动在端口 8080\n";
$server->run();

客户端 JavaScript 代码

<!DOCTYPE html>
<html>
<head>WebSocket 示例</title>
</head>
<body>
    <div id="messages"></div>
    <input type="text" id="messageInput" placeholder="输入消息">
    <button onclick="sendMessage()">发送</button>
    <script>
    // 创建 WebSocket 连接
    const ws = new WebSocket('ws://localhost:8080');
    // 连接打开
    ws.addEventListener('open', function(e) {
        console.log('WebSocket 连接已建立');
        addMessage('系统', '已连接到服务器');
    });
    // 接收消息
    ws.addEventListener('message', function(e) {
        const data = JSON.parse(e.data);
        switch (data.type) {
            case 'welcome':
                addMessage('服务器', data.message);
                break;
            case 'broadcast':
                addMessage(`用户 ${data.from}`, data.message);
                break;
            case 'private':
                addMessage(`私信来自 ${data.from}`, data.message);
                break;
            default:
                addMessage('未知', JSON.stringify(data));
        }
    });
    // 连接关闭
    ws.addEventListener('close', function(e) {
        console.log('WebSocket 连接已关闭');
        addMessage('系统', '连接已断开');
    });
    // 错误处理
    ws.addEventListener('error', function(e) {
        console.error('WebSocket 错误:', e);
        addMessage('系统', '连接错误');
    });
    // 发送消息
    function sendMessage() {
        const input = document.getElementById('messageInput');
        const message = input.value.trim();
        if (message) {
            ws.send(JSON.stringify({
                type: 'broadcast',
                message: message
            }));
            input.value = '';
        }
    }
    // 添加消息到界面
    function addMessage(sender, message) {
        const div = document.getElementById('messages');
        div.innerHTML += `<p><strong>${sender}:</strong> ${message}</p>`;
    }
    </script>
</body>
</html>

使用 Swoole(高性能方案)

安装 Swoole

pecl install swoole

服务器端代码

<?php
$server = new Swoole\WebSocket\Server("0.0.0.0", 9501);
// 监听 WebSocket 连接打开事件
$server->on('open', function (Swoole\WebSocket\Server $server, $request) {
    echo "新连接: {$request->fd}\n";
    $server->push($request->fd, json_encode([
        'type' => 'welcome',
        'message' => '欢迎连接到 Swoole WebSocket 服务器'
    ]));
});
// 监听消息事件
$server->on('message', function (Swoole\WebSocket\Server $server, $frame) {
    echo "收到消息: {$frame->data}\n";
    // 广播消息给所有客户端
    foreach ($server->connections as $fd) {
        if ($fd !== $frame->fd) {
            $server->push($fd, $frame->data);
        }
    }
});
// 监听连接关闭事件
$server->on('close', function ($ser, $fd) {
    echo "连接关闭: {$fd}\n";
});
echo "Swoole WebSocket 服务器启动在端口 9501\n";
$server->start();

使用第三方推送服务

Pusher(推荐)

<?php
require 'vendor/autoload.php';
use Pusher\Pusher;
$options = array(
    'cluster' => 'ap1',
    'useTLS' => true
);
$pusher = new Pusher(
    'your-app-key',
    'your-app-secret',
    'your-app-id',
    $options
);
// 推送消息
$data['message'] = 'Hello World!';
$pusher->trigger('my-channel', 'my-event', $data);

Firebase Cloud Messaging (FCM)

<?php
function sendFCMNotification($deviceToken, $title, $body) {
    $url = 'https://fcm.googleapis.com/fcm/send';
    $fields = [
        'to' => $deviceToken,
        'notification' => [
            'title' => $title,
            'body' => $body,
            'sound' => 'default'
        ],
        'data' => [
            'type' => 'notification',
            'action' => 'open_page'
        ]
    ];
    $headers = [
        'Authorization: key=' . YOUR_SERVER_KEY,
        'Content-Type: application/json'
    ];
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($fields));
    $result = curl_exec($ch);
    curl_close($ch);
    return $result;
}

选择建议

技术方案 适用场景 优点 缺点
SSE 实时通知、数据推送 实现简单,原生支持 单向通信,浏览器兼容性有限
WebSocket 即时通讯、在线游戏 双向通信,实时性好 需要特殊服务器支持
Pusher 快速集成推送 开箱即用,功能完善 有费用限制
FCM 移动推送 免费,覆盖面广 依赖第三方服务

生产环境注意事项

  1. 性能优化

    • 使用连接池管理连接
    • 设置合理的超时时间
    • 考虑使用消息队列(如 RabbitMQ)
  2. 安全性

    • 验证客户端身份
    • 加密敏感数据
    • 限制推送频率
  3. 可靠性

    • 实现断线重连机制
    • 保存未推送消息
    • 监控连接状态

选择哪种推送方案取决于您的具体需求:如果只是简单的服务器推送消息,SSE 即可;如果需要双向实时通信,推荐使用 WebSocket。

上一篇PHP 怎么PHP 后台同步

下一篇当前分类已是最新一篇

抱歉,评论功能暂时关闭!