本文目录导读:

在PHP中实现“双人操作”通常有几种常见的应用场景,我这里针对实时双人协作(如双人编辑文档、双人游戏对战等)给出几种主流实现方案:
最基础方案:轮询 + 数据库(适合学习/小规模)
// 用户A写入操作
// save_action.php
<?php
session_start();
$action = $_POST['action'];
$user_id = $_SESSION['user_id'];
// 存入数据库
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');
$stmt = $pdo->prepare("INSERT INTO actions (user_id, action, created_at) VALUES (?, ?, NOW())");
$stmt->execute([$user_id, $action]);
// 返回给对方的最新状态
$stmt = $pdo->query("SELECT * FROM actions WHERE user_id != $user_id ORDER BY id DESC LIMIT 1");
$other_action = $stmt->fetch();
echo json_encode($other_action);
?>
<!-- 前端定时轮询 -->
<script>
function checkOtherAction() {
fetch('check_actions.php')
.then(res => res.json())
.then(data => {
if(data.action) {
// 执行对方操作
applyAction(data.action);
}
});
}
setInterval(checkOtherAction, 1000); // 每秒检查
</script>
推荐方案:WebSocket + Ratchet(实时双向)
安装依赖
composer require cboden/ratchet
服务端代码 (chat_server.php)
<?php
require 'vendor/autoload.php';
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class DualPlayer implements MessageComponentInterface {
protected $clients;
protected $rooms = [];
public function __construct() {
$this->clients = new \SplObjectStorage;
}
public function onOpen(ConnectionInterface $conn) {
$this->clients->attach($conn);
echo "新连接: {$conn->resourceId}\n";
}
public function onMessage(ConnectionInterface $from, $msg) {
$data = json_decode($msg);
switch($data->type) {
case 'join_room':
// 加入房间
$room = $data->room;
$this->rooms[$room][] = $from;
$from->room = $room;
// 如果有两人,通知开始
if(count($this->rooms[$room]) == 2) {
foreach($this->rooms[$room] as $client) {
$client->send(json_encode([
'type' => 'game_start',
'message' => '双方已就绪!'
]));
}
}
break;
case 'action':
// 转发动作给房间内另一个人
$room = $from->room;
foreach($this->rooms[$room] as $client) {
if($client !== $from) {
$client->send(json_encode([
'type' => 'opponent_action',
'action' => $data->action
]));
}
}
break;
}
}
public function onClose(ConnectionInterface $conn) {
$this->clients->detach($conn);
if(isset($conn->room)) {
unset($this->rooms[$conn->room]);
}
}
public function onError(ConnectionInterface $conn, \Exception $e) {
$conn->close();
}
}
// 启动WebSocket服务器
$server = IoServer::factory(
new HttpServer(
new WsServer(
new DualPlayer()
)
),
8080
);
echo "WebSocket服务器运行在 ws://localhost:8080\n";
$server->run();
前端HTML (dual_game.html)
<!DOCTYPE html>
<html>
<head>双人协作</title>
</head>
<body>
<div id="status">等待对手加入...</div>
<div id="gameArea">
<button onclick="sendAction('left')">←</button>
<button onclick="sendAction('right')">→</button>
<button onclick="sendAction('jump')">↑</button>
</div>
<div id="opponentAction"></div>
<script>
const ws = new WebSocket('ws://localhost:8080');
const roomId = 'room_' + Math.floor(Math.random() * 1000);
ws.onopen = () => {
ws.send(JSON.stringify({
type: 'join_room',
room: roomId
}));
};
ws.onmessage = (e) => {
const data = JSON.parse(e.data);
if(data.type === 'game_start') {
document.getElementById('status').textContent = data.message;
} else if(data.type === 'opponent_action') {
document.getElementById('opponentAction').textContent =
'对手执行: ' + data.action;
// 这里可以写对手动作的视觉反馈
}
};
function sendAction(action) {
ws.send(JSON.stringify({
type: 'action',
action: action
}));
}
</script>
</body>
</html>
启动服务端
php chat_server.php
然后用两个浏览器打开 dual_game.html,它们会配对到同一个房间。
文件锁方案(最简单的双人文件编辑)
<?php
// 双人编辑同一个文件
$filename = 'shared_data.json';
$fp = fopen($filename, 'r+');
// 获取独占锁
if (flock($fp, LOCK_EX)) {
// 读取当前数据
$data = json_decode(file_get_contents($filename), true);
// 用户A修改
$data['user1_score'] = $_POST['score'];
// 写入回文件
ftruncate($fp, 0);
fwrite($fp, json_encode($data));
fflush($fp);
flock($fp, LOCK_UN);
}
fclose($fp);
推荐的生产级方案
- Pusher (第三方WebSocket服务)
- Socket.IO + PHP (通过Node.js中转)
- Laravel Echo + Laravel WebSockets
总结对比
| 方案 | 延迟 | 实现难度 | 适合场景 |
|---|---|---|---|
| 轮询 | 高 | 简单 | 学习演示 |
| WebSocket | 低 | 中等 | 实时游戏/协作 |
| 文件锁 | 高 | 简单 | 双人编辑 |
| Pusher | 低 | 中等 | 生产环境 |
对于真正的实时双人操作,强烈建议使用WebSocket方案,如果只是简单的双人轮流操作(类似回合制),用HTTP请求+数据库就足够了。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播