摘要:最近帮表弟做了个在线答题小程序,他非要加实时PK功能。作为老程序员,我第一反应就是"这还不简单?WebSocket搞起来!"结果一动手发现,要实现真正的实时同步,里面门道还真不少。今天就用最接地气的方式,带你从0到1搭建一个能实际运行的答题PK系统。
最近帮表弟做了个在线答题小程序,他非要加实时PK功能。作为老程序员,我第一反应就是"这还不简单?WebSocket搞起来!"结果一动手发现,要实现真正的实时同步,里面门道还真不少。今天就用最接地气的方式,带你从0到1搭建一个能实际运行的答题PK系统。
为什么选WebSocket?
传统HTTP请求就像写信,发一封等一封回。而WebSocket是打电话,接通后随时能聊。答题PK要的就是这种"对方刚选完答案你屏幕就跳结果"的实时感。我们选Spring Boot的WebSocket模块,开箱即用,三行注解就能搞定。
后端实现三板斧
建立连接中枢先搭个消息中转站,用@ServerEndpoint标注的WebSocket服务类:
publicstaticsynchronized Player match(Player newPlayer) {
for (Player p : players.values) {
if (p.isWaiting && !p.getUserId.equals(newPlayer.getUserId)) {
p.setWaiting(false);
newPlayer.setWaiting(false);
}
}
newPlayer.setWaiting(true);
@OnMessage
publicvoidonMessage(String msg, Session session) {
Playercurrent= players.get(session.getId);
Playeropponent= getOpponent(current);
if (opponent != null) {
opponent.getSession.getBasicRemote.sendText(msg);
}
}
前端实战技巧
连接管理javascriptlet ws = newWebSocket(`ws://${location.host}/pk?userId=${localStorage.userId}`);
ws.onopen = => {
showStatus("等待对手...");
// 30秒没匹配到就提示
setTimeout( => {
if(ws.readyState === WebSocket.CONNECTING) {
showError("匹配超时,请重试");
ws.close;
}
}, 30000);
};同步答题状态javascript
// 收到对手操作时
ws.onmessage = (e) => {
const data = JSON.parse(e.data);
if(data.type === "answer") {
// 禁用对手的选项
document.getElementById(`opt${data.option}`).disabled = true;
// 显示对手选择
showOpponentChoice(data.option);
}
};倒计时同步大法javascript
// 服务器下发开始时间戳
let serverStartTime = Date.now + 1000; // 预留1秒网络延迟
let timer = setInterval( => {
let left = Math.max(0, Math.floor((serverStartTime - Date.now)/1000));
document.getElementById("timer").innerText = left;
if(left
clearInterval(timer);
submitAnswer; // 时间到自动交卷
}
}, 1000);网络延迟处理
用服务器时间戳同步:开始答题时,服务器下发统一的时间戳,客户端根据这个时间计算倒计时,避免双方时间不同步。断线重连机制
ws.onclose = (e) => {
if(e.code !== 1000) { // 主动关闭不算
showReconnectBtn;
// 3秒后尝试重连
setTimeout( => reconnect, 3000);
}
};防作弊检测答题速度检测:正常人类阅读+选择至少需要3秒,过快提交的标记为可疑操作日志对比:服务端记录双方操作时间线,回放检查是否同步
测试避坑指南
用两个浏览器窗口模拟双人,用Chrome的--user-data-dir参数开独立窗口手机端测试要关闭省电模式,否则可能杀后台导致连接中断压力测试用JMeter的WebSocket插件,模拟1000+并发看是否崩溃题目推送改用Redis Stream,避免内存存储瓶颈增加房间概念,支持多组同时PK添加观战模式,用发布-订阅模式实现这个方案在本地测试能做到80ms内的操作同步延迟,实际生产环境配合CDN和负载均衡,支撑万人同时在线不是梦。最关键的是,整个核心逻辑代码不到300行,真正实现了"小而美"的实时系统。现在就去试试,让你的用户也体验一把"心有灵犀"的答题PK吧!
来源:洪生鹏一点号
免责声明:本站系转载,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请在30日内与本站联系,我们将在第一时间删除内容!