本文目录导读:

我将为您详细介绍 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 支持双向通信,适合实时交互场景,需要安装 Ratchet 或 Swoole 等库。
使用 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 | 移动推送 | 免费,覆盖面广 | 依赖第三方服务 |
生产环境注意事项
-
性能优化:
- 使用连接池管理连接
- 设置合理的超时时间
- 考虑使用消息队列(如 RabbitMQ)
-
安全性:
- 验证客户端身份
- 加密敏感数据
- 限制推送频率
-
可靠性:
- 实现断线重连机制
- 保存未推送消息
- 监控连接状态
选择哪种推送方案取决于您的具体需求:如果只是简单的服务器推送消息,SSE 即可;如果需要双向实时通信,推荐使用 WebSocket。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播