websocket是网页围棋实时对弈的核心技术,通过长连接实现落子消息双向推送;客户端发送坐标+颜色,服务端校验后广播给对手并持久化为sgf棋谱;支持房间绑定、断线重连与棋谱同步。

WebSocket 是实现网页端围棋对弈实时棋谱同步的核心技术,它让浏览器与服务器保持长连接,双方可随时双向推送落子动作,无需轮询或刷新页面。关键在于:客户端只发送“坐标+颜色”(如 {"x":3,"y":15,"color":"B"}),服务端广播给对手,并持久化存入棋谱结构(如 SGF 或自定义 JSON)。
建立稳定 WebSocket 连接并绑定对弈房间
用户进入对局前,前端通过唯一房间 ID(如 URL 参数 ?room=abc123)发起连接:
const ws = new WebSocket(`wss://game.example.com/ws?room=${roomId}`);
ws.onopen = () => console.log("已加入房间:" + roomId);
ws.onerror = (e) => console.error("连接失败", e);
服务端(Node.js + ws 库为例)需校验房间有效性、限制两人上限,并将 socket 加入对应房间的 Map:
- 每个房间维护一个
players = { black: ws1, white: ws2 }对象 - 连接关闭时及时清理房间状态,避免残留
- 拒绝同一用户重复加入或三人以上接入
落子消息格式统一 & 实时广播
前端点击棋盘后,不直接操作 DOM,而是封装标准消息发给服务端:
function makeMove(x, y, color) {
ws.send(JSON.stringify({ type: "move", x, y, color, timestamp: Date.now() }));
}
服务端收到后验证合法性(是否轮到该方、位置是否空、是否超时等),再转发给另一方:
- 消息必须含
type字段便于路由(如区分 move / resign / timeup) - 广播时不发回原发送者,避免本地重复渲染
- 添加
sequence序号或时间戳,防止客户端消息乱序
服务端生成并同步 SGF 棋谱结构
每步落子都应追加到内存中的 SGF 树节点,并在终局时保存完整棋谱。推荐用 sgf-parser 或轻量手写生成器:
- 初始 SGF 模板包含
GM[1](围棋)、FF[4]、AP[WebGo/1.0]等必要头字段 - 每次落子转为 SGF 属性,如黑子 D4 →
B[dd](SGF 坐标是小写字母 a–s,从右下角起算) - 服务端维护一个
sgfMoves = []数组,push 后同步给双方,前端可用sgf-tools渲染回放 - 支持导出按钮:前端请求
/sgf?room=abc123,服务端返回纯文本 SGF 内容供下载
断线重连与棋谱恢复机制
移动端易断网,需保障重连后能续上下一回合,而非丢子或错色:
- 服务端记录每局最后 50 步(或全部)到 Redis,key 为
game:abc123:moves - 前端重连成功后立即发
{"type":"sync","seq":lastKnownSeq},服务端比对并补发缺失步数 - 客户端本地缓存最近几步(localStorage),在网络恢复后校验并提交未确认的落子
- 棋盘状态以服务端为准,前端收到全量 moves 后清空本地状态再重建
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











