本文目录导读:

我将为您提供一个完整的PHP实时数据接口解决方案,包含多种实现方式。
SSE (Server-Sent Events) 实时推送
服务端实现 (sse_server.php)
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Connection: keep-alive');
header('X-Accel-Buffering: no'); // 禁用Nginx缓冲
// 关闭执行时间限制
set_time_limit(0);
// 确保数据实时输出
while (ob_get_level() > 0) {
ob_end_flush();
}
ob_implicit_flush(true);
// 连接断开检测
ignore_user_abort(false);
echo "retry: 3000\n"; // 重连间隔3秒
// 模拟实时数据推送
$counter = 0;
while (!connection_aborted()) {
$counter++;
// 获取实时数据(这里可以是数据库查询、API调用等)
$data = [
'id' => $counter,
'timestamp' => date('Y-m-d H:i:s'),
'value' => rand(1, 100),
'message' => "第{$counter}条实时数据"
];
// 发送数据
echo "id: {$counter}\n";
echo "data: " . json_encode($data, JSON_UNESCAPED_UNICODE) . "\n\n";
// 刷新输出缓冲
flush();
// 每2秒推送一次
sleep(2);
// 测试用:到达10条后停止
if ($counter >= 10) {
echo "event: close\ndata: {\"message\":\"连接关闭\"}\n\n";
flush();
break;
}
}
?>
客户端实现 (sse_client.php)
<!DOCTYPE html>
<html>
<head>SSE 实时数据</title>
<style>
#data-container {
max-height: 400px;
overflow-y: scroll;
border: 1px solid #ddd;
padding: 10px;
margin: 20px;
}
.data-item {
margin: 10px 0;
padding: 10px;
background: #f5f5f5;
border-radius: 5px;
}
</style>
</head>
<body>
<h2>SSE 实时数据流</h2>
<div id="data-container"></div>
<script>
// 连接状态显示
const container = document.getElementById('data-container');
// 创建EventSource连接
const eventSource = new EventSource('sse_server.php');
// 连接打开
eventSource.onopen = function(e) {
container.innerHTML += '<div class="data-item" style="color:green;">✓ 连接成功</div>';
};
// 接收普通消息
eventSource.onmessage = function(e) {
const data = JSON.parse(e.data);
console.log('收到数据:', data);
const div = document.createElement('div');
div.className = 'data-item';
div.innerHTML = `
<strong>ID:</strong> ${data.id}<br>
<strong>时间:</strong> ${data.timestamp}<br>
<strong>值:</strong> ${data.value}<br>
<strong>消息:</strong> ${data.message}
`;
container.appendChild(div);
// 自动滚动到底部
container.scrollTop = container.scrollHeight;
};
// 自定义事件
eventSource.addEventListener('close', function(e) {
container.innerHTML += '<div class="data-item" style="color:red;">× 连接关闭</div>';
eventSource.close();
});
// 错误处理
eventSource.onerror = function(e) {
console.error('连接错误:', e);
container.innerHTML += '<div class="data-item" style="color:red;">⚠ 连接断开,正在重连...</div>';
};
// 手动断开连接
function disconnect() {
eventSource.close();
container.innerHTML += '<div class="data-item" style="color:orange;">✕ 已手动断开连接</div>';
}
</script>
</body>
</html>
WebSocket 实时通信
WebSocket 服务器 (websocket_server.php)
<?php
// 简单的WebSocket服务器实现
class WebSocketServer {
private $clients = [];
private $socket;
public function __construct($host = '0.0.0.0', $port = 8080) {
$this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($this->socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($this->socket, $host, $port);
socket_listen($this->socket);
echo "WebSocket服务器启动在 ws://$host:$port\n";
}
public function run() {
while (true) {
$read = array_merge([$this->socket], $this->clients);
$write = $except = null;
socket_select($read, $write, $except, null);
foreach ($read as $socket) {
if ($socket === $this->socket) {
// 新连接
$client = socket_accept($this->socket);
if ($client) {
$this->clients[] = $client;
echo "新客户端连接,当前客户端数: " . count($this->clients) . "\n";
}
} else {
// 处理客户端数据
$data = @socket_read($socket, 1024, PHP_BINARY_READ);
if ($data === false) {
// 连接关闭
$this->removeClient($socket);
} else if ($data) {
// 处理WebSocket握手
if (strpos($data, 'Sec-WebSocket-Key') !== false) {
$this->handshake($socket, $data);
} else {
// 处理消息
$decoded = $this->decodeFrame($data);
echo "收到消息: " . $decoded . "\n";
// 发送实时数据给所有客户端
$response = [
'type' => 'realtime',
'data' => $this->getRealtimeData(),
'timestamp' => time()
];
$this->sendToAll(json_encode($response));
}
}
}
}
}
}
private function handshake($client, $request) {
preg_match('/Sec-WebSocket-Key:\s(.*?)\r\n/', $request, $matches);
$key = $matches[1];
$accept = base64_encode(sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
$response = "HTTP/1.1 101 Switching Protocols\r\n";
$response .= "Upgrade: websocket\r\n";
$response .= "Connection: Upgrade\r\n";
$response .= "Sec-WebSocket-Accept: {$accept}\r\n\r\n";
socket_write($client, $response);
}
private function decodeFrame($data) {
$secondByte = ord($data[1]);
$length = $secondByte & 127;
if ($length <= 125) {
$maskStart = 2;
} else if ($length == 126) {
$length = unpack('n', substr($data, 2, 2))[1];
$maskStart = 4;
} else {
$length = unpack('N', substr($data, 2, 4))[1];
$maskStart = 10;
}
$masks = substr($data, $maskStart, 4);
$data = substr($data, $maskStart + 4);
$decoded = '';
for ($i = 0; $i < strlen($data); $i++) {
$decoded .= $data[$i] ^ $masks[$i % 4];
}
return $decoded;
}
private function encodeFrame($message) {
$frame = [];
$len = strlen($message);
$frame[0] = 0x81; // text frame
if ($len <= 125) {
$frame[1] = $len;
} else if ($len <= 65535) {
$frame[1] = 126;
$frame[2] = ($len >> 8) & 255;
$frame[3] = $len & 255;
} else {
$frame[1] = 127;
for ($i = 7; $i >= 0; $i--) {
$frame[$i + 2] = ($len >> ($i * 8)) & 255;
}
}
$frame = array_merge($frame, unpack('C*', $message));
return call_user_func_array('pack', array_merge(['C*'], $frame));
}
private function getRealtimeData() {
// 这里可以替换为真实的数据库查询或API调用
return [
'id' => time(),
'value' => rand(1, 1000),
'data' => date('Y-m-d H:i:s')
];
}
private function sendToAll($message) {
foreach ($this->clients as $client) {
socket_write($client, $this->encodeFrame($message));
}
}
private function removeClient($socket) {
$key = array_search($socket, $this->clients);
if ($key !== false) {
unset($this->clients[$key]);
socket_close($socket);
echo "客户端断开,剩余客户端数: " . count($this->clients) . "\n";
}
}
public function __destruct() {
socket_close($this->socket);
}
}
// 启动服务器
$server = new WebSocketServer('localhost', 8080);
$server->run();
?>
WebSocket 客户端 (websocket_client.php)
<!DOCTYPE html>
<html>
<head>WebSocket 实时数据</title>
<style>
#logs {
margin: 20px;
padding: 10px;
border: 1px solid #ddd;
max-height: 400px;
overflow-y: auto;
}
.log-item {
padding: 5px;
margin: 5px 0;
background: #f9f9f9;
}
</style>
</head>
<body>
<h2>WebSocket 实时数据</h2>
<button onclick="connect()">连接</button>
<button onclick="disconnect()">断开</button>
<button onclick="sendData()">发送数据</button>
<div id="logs"></div>
<script>
let ws = null;
const logs = document.getElementById('logs');
function addLog(message) {
const div = document.createElement('div');
div.className = 'log-item';
div.textContent = message;
logs.appendChild(div);
logs.scrollTop = logs.scrollHeight;
}
function connect() {
if (ws && ws.readyState === WebSocket.OPEN) {
addLog('已连接');
return;
}
ws = new WebSocket('ws://localhost:8080');
ws.onopen = function() {
addLog('✓ 已连接到WebSocket服务器');
};
ws.onmessage = function(event) {
addLog('收到数据: ' + event.data);
};
ws.onerror = function(error) {
addLog('❌ 发生错误: ' + error.message);
};
ws.onclose = function() {
addLog('连接已关闭');
};
}
function disconnect() {
if (ws) {
ws.close();
addLog('已断开连接');
}
}
function sendData() {
if (ws && ws.readyState === WebSocket.OPEN) {
const data = {
type: 'request',
data: '获取实时数据'
};
ws.send(JSON.stringify(data));
addLog('发送数据: ' + JSON.stringify(data));
} else {
addLog('未连接服务器');
}
}
</script>
</body>
</html>
轮询实时接口
轮询接口 (polling_api.php)
<?php
// API响应
header('Content-Type: application/json');
// 获取请求参数
$lastId = isset($_GET['last_id']) ? (int)$_GET['last_id'] : 0;
// 模拟数据库查询(这里使用文件存储来模拟)
$dataFile = 'data.json';
// 生成或获取数据
$data = [
'last_id' => $lastId + 1,
'items' => [],
'timestamp' => date('Y-m-d H:i:s')
];
// 模拟生成新数据
for ($i = 1; $i <= 3; $i++) {
$data['items'][] = [
'id' => $lastId + $i,
'value' => rand(1000, 9999),
'time' => date('Y-m-d H:i:s')
];
}
// 返回JSON数据
echo json_encode($data);
?>
轮询客户端
<!DOCTYPE html>
<html>
<head>轮询实时数据</title>
<script>
let lastId = 0;
// 定期轮询
function pollData() {
fetch(`polling_api.php?last_id=${lastId}`)
.then(response => response.json())
.then(data => {
if (data.items.length > 0) {
lastId = data.last_id;
console.log('添加新数据:', data.items);
}
})
.catch(error => console.error('轮询错误:', error));
}
// 每3秒轮询一次
setInterval(pollData, 3000);
// 立即执行一次
pollData();
</script>
</head>
<body>
<h2>轮询实时数据</h2>
</body>
</html>
通用RESTful API接口
REST API (api.php)
<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
// 简单的路由处理
$method = $_SERVER['REQUEST_METHOD'];
$path = isset($_GET['path']) ? $_GET['path'] : '/';
// 数据库连接(示例使用PDO)
$pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
switch ($method) {
case 'GET':
if ($path === 'realtime-data') {
// 获取实时数据
$stmt = $pdo->prepare("SELECT * FROM realtime_data ORDER BY id DESC LIMIT 10");
$stmt->execute();
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode([
'success' => true,
'data' => $data,
'timestamp' => time()
]);
}
break;
case 'POST':
// 添加新数据
$input = json_decode(file_get_contents('php://input'), true);
$stmt = $pdo->prepare("INSERT INTO realtime_data (value, description) VALUES (?, ?)");
$stmt->execute([$input['value'], $input['description']]);
echo json_encode([
'success' => true,
'message' => '数据添加成功',
'id' => $pdo->lastInsertId()
]);
break;
case 'PUT':
// 更新数据
break;
case 'DELETE':
// 删除数据
break;
default:
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
}
?>
最佳实践建议
配置与优化 (config.php)
<?php
// 实时数据配置
return [
'sse' => [
'interval' => 2, // 推送间隔(秒)
'retry_time' => 3000, // 重连时间(毫秒)
'max_duration' => 3600 // 最大持续时间
],
'websocket' => [
'host' => '0.0.0.0',
'port' => 8080,
'ping_interval' => 30, // 心跳间隔
'max_connections' => 1000
],
'polling' => [
'default_interval' => 5, // 轮询间隔(秒)
'max_interval' => 60, // 最大间隔
'http_client' => [
'timeout' => 10,
'connect_timeout' => 5
]
],
'cache' => [
'enabled' => true,
'driver' => 'redis',
'ttl' => 30 // 缓存生命周期(秒)
],
'security' => [
'api_key' => 'your-secret-key',
'rate_limit' => 100, // 每分钟请求限制
'ip_whitelist' => [] // IP白名单
]
];
?>
这些实现方案各有优缺点:
- SSE:简单,自动化重连,适合服务器到客户端的单向推送
- WebSocket:双向通信,实时性最好,适合聊天、游戏等应用
- 轮询:兼容性最好,实现简单,适合低频更新
- REST API:通用性强,适合标准CRUD操作
选择哪种方案取决于您的具体需求、服务器架构和客户端环境,建议根据实际场景选择合适的方案,或者组合使用。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播