基于websockets库实现WebSocket通信:构建在线四子棋游戏(第一部分)
概述
本文将介绍如何使用Python的websockets库构建一个基于WebSocket协议的在线四子棋游戏。WebSocket协议提供了浏览器与服务器之间的全双工通信通道,非常适合需要实时交互的在线游戏场景。
WebSocket与HTTP的对比
传统HTTP协议存在以下局限性:
- 基于请求-响应模式,服务器无法主动推送数据
- 实现实时通信需要轮询或长轮询,带来额外开销
WebSocket协议的优势:
- 建立持久连接后,服务器和客户端可以随时互相发送消息
- 低延迟,适合实时交互场景
- 减少不必要的网络流量
环境准备
安装websockets库
pip install websockets
验证安装:
python -m websockets --version
项目结构
前端文件
connect4.js
:游戏界面逻辑connect4.css
:游戏样式index.html
:主页面main.js
:前端主逻辑
后端文件
connect4.py
:游戏核心逻辑app.py
:WebSocket服务器
构建WebSocket服务器
基本服务器结构
import asyncio
import websockets
async def handler(websocket):
async for message in websocket:
print(message)
async def main():
async with websockets.serve(handler, "", 8001):
await asyncio.get_running_loop().create_future()
if __name__ == "__main__":
asyncio.run(main())
关键点说明:
websockets.serve()
创建WebSocket服务器handler
协程处理每个连接- 使用
async for
循环持续接收消息
消息处理模式
WebSocket通信中常见的三种消息处理方式:
- 使用
recv()
方法接收单条消息 - 使用
async for
循环持续接收消息(推荐) - 使用
while True
循环配合异常处理
前端实现
建立WebSocket连接
const websocket = new WebSocket("ws://localhost:8001/");
消息格式设计
采用JSON格式,包含type
字段标识消息类型:
- 游戏动作:
{type: "play", column: 3}
- 游戏结果:
{type: "win", player: "red"}
- 错误信息:
{type: "error", message: "..."}
发送消息示例
websocket.send(JSON.stringify({
type: "play",
column: 3
}));
接收消息处理
websocket.addEventListener("message", ({data}) => {
const event = JSON.parse(data);
switch(event.type) {
case "play":
playMove(board, event.player, event.column, event.row);
break;
case "win":
setTimeout(() => alert(`Player ${event.player} wins!`), 100);
break;
case "error":
setTimeout(() => alert(event.message), 100);
break;
}
});
游戏逻辑集成
游戏状态管理
from connect4 import Connect4
async def handler(websocket):
game = Connect4()
player = PLAYER1
async for message in websocket:
event = json.loads(message)
if event["type"] == "play":
try:
row = game.play(player, event["column"])
await websocket.send(json.dumps({
"type": "play",
"player": player,
"column": event["column"],
"row": row
}))
if game.winner:
await websocket.send(json.dumps({
"type": "win",
"player": game.winner
}))
player = PLAYER2 if player == PLAYER1 else PLAYER1
except RuntimeError as exc:
await websocket.send(json.dumps({
"type": "error",
"message": str(exc)
}))
游戏规则实现
connect4.py
中实现了:
- 棋盘状态管理
- 落子逻辑
- 胜负判断
调试技巧
- 启用调试日志:
import logging
logging.basicConfig(format="%(message)s", level=logging.DEBUG)
- 服务器重启注意事项:
- 修改代码后必须重启WebSocket服务器
- HTTP服务器会自动加载修改后的静态文件
总结
本部分教程实现了:
- WebSocket服务器的基本结构
- 前后端通信协议设计
- 游戏核心逻辑集成
- 基本的错误处理机制
目前实现的是单浏览器双人游戏模式,后续将扩展为多浏览器在线对战功能。
常见问题
Q: 为什么需要setTimeout
包装alert调用?
A: 避免alert阻塞UI渲染,确保动画效果可见后再显示提示。
Q: 如何处理连接中断?
A: WebSocket会自动抛出ConnectionClosedOK
异常,可以在async for
循环外捕获处理。
Q: 消息格式为什么选择JSON? A: JSON具有良好的人类可读性,且被所有现代浏览器原生支持,便于调试和开发。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考