Hello各位小伙伴们,这篇博客我将给梳理我做这个关于websocket的网页五子棋项目的过程~~~
项目代码 --- git仓库地址:https://gitee.com/jinhong-c/gobang
项目成果展示图:





1.项目的大致思路
2.使用到的关键技术
3.websocket的简介
4.数据库设计
5.匹配模块 --- 前后端交互接口
6.实现匹配模块机制
7.匹配算法思路
8.线程安全问题
9.对战模块 ---- 前后端交互接口
10.部署
1.项目大致思路
1.)用户模块
用户的登录和注册
管理用户的天梯分数,比赛场数,获胜场数.....
2.)匹配模块
根据用户的天梯分数,实现适合的匹配机制
3.)对战模块
将俩个匹配到的用户放到同一个房间中,双方通过网页的形式进行下棋对战
2.使用到的关键技术
1.) Java
2.)Spring
3.)SpringBoot
4.)SpringMVC
5.)HTML
6.)CSS
7.)AJAX
8.)MySQL
9.)MyBatis
10.)WebSocket
3.WebSocket简介

WebSocket其实就是实现消息推送的功能! ! !
什么是消息推送呢???
当玩家1在棋盘上落子时,玩家1客户端就需要主动给服务器发送一个消息,告诉服务器这个棋子落在哪个位置~~~
然后服务器发送给玩家2, 玩家2也就需要得到玩家1落子的位置
但是我们不能使用HTTP来实现这个功能,因为想使用HTTP实现这个功能,就需要使用"轮询"的机制而轮询的机制开销是比较大的,成本也比较高,因为需要客户端在指定的时间内,比如100ms,500ms等等时间内不断向服务器询问时候有消息,这样效率也是比较低,也会浪费系统资源
而我们使用websocket就可以很好减少系统资源的问题,当服务器接收到某一个玩家的消息时,服务器就会自动给另一个玩家发送信息,告诉他那个玩家棋子落在了哪~~~~
4.数据库设计
使用数据库存储 "用户登录" "注册信息" "天梯积分" "比赛总场数" "比赛获胜场数" 等等....
sql
create database if not exists gobang;
use gobang;
drop table if exists user;
create table user (
userId int primary key auto_increment,
username varchar(50) unique,
password varchar(50),
score int, -- 天梯积分
totalCount int, -- 比赛总场数
winCount int -- 获胜场数
);
insert into user values(null, "zhangsan", '123', 100, 0, 0);
insert into user values(null, "lisi", "123", 200, 0, 0);
insert into user values(null, "wangwu", "123", 300, 0, 0);
5.匹配模块 --- 前后端交互接口
登录时前后端接口的交互如下:

注册时前后端接口的交互如下:

我们需要让服务器获取当前登录的用户信息
因为程序运行的过程中,用户登录后,通过客户端随时使用这个接口,访问服务器来获取自身的信息

6.实现匹配模块机制
匹配模块主要是让多用户,在游戏大厅中可以进行匹配,并且将实力接近的玩家匹配在一起
但是匹配模块机制也是依赖消息推送机制(webSocket)

当玩家发送匹配请求的时候,这个事件就已经是确定的了
但是服务器应该啥时候告诉玩家,你已经匹配到另一个玩家了呢??? ---- 就需要等待匹配结束才告知
正是因为服务器自己也不确定啥时候应该告诉玩家匹配的结果,因此就需要依赖消息推送机制, 当服务器匹配成功之后,就主动告诉当前排到的所有玩家 "你排到了~~~"
webSocket可以传输文本数据, 也能传输二进制数据,所以直接设计成让websocket传输 json格式的文本数据即可
匹配请求:
客户端通过websocket给服务器发送一个json格式的文本数据
ws://127.0.0.1:8080/findMatch
{
message: 'startMatch' / 'stopMatch' //开始匹配/结束匹配
}
通过websocket传输数据的时候,数据中不必携带用户身份信息,当前用户身份信息在前面登录过程中已经存储再HttpSession中了,websocket也可以拿到之前登录好的HttpSession中的信息
匹配相应1(这个响应是客户端给服务器发送匹配请求之后,服务器立即返回的匹配响应(比较虚假)):
ws://127.0.0.1:8080/findMatch
{
ok : true //匹配成功
reason: //匹配如果失败,显示匹配失败的原因
message: 'startMatch' / 'stopMatch'
}
匹配相应2(这个相应是正真匹配到对手之后,服务器主动推送回来的相应信息(比较真实))
ws://127.0.0.1:8080/findMatch
{
ok: true //匹配成功
reason: //匹配如果失败,显示匹配失败的原因
message: 'matchSuccess'
}
7.匹配算法思路
目标: 从待匹配的玩家中,选出分数尽量近的玩家
将所有玩家按照分数,分为三类:
1.>Normal score < 2000
2.>High score >= 2000 && score <= 3000
3.>VeryHigh score >= 3000
给这三个等级,分配三个不同的队列!!!!
根据当前玩家的分数, 来把这个玩家的用户信息放到对应的队列中
接下来就专门搞个专门的线程,不停的扫描这个匹配队列,只要说队列里面的玩家凑成一对,把这一对玩家取出来,然后放到一个游戏的房间中即可~~~~

8.线程安全问题
使用synchronized进行加锁
此处进行加锁的时候,要明确, 如果是多个线程访问不同的队列时候, 就不涉及线程安全问题
但是多个线程访问同一个队列时候, 就需要加锁~~~~
所以我们在加锁时候选取的对象,就是normalQueue, highQueue, veryHighQueue这三个队列本身


9.对战模块 ---- 前后端交互接口


10.部署
1.>将数据库中的数据给构造好 ---- 复制 IDEA 中的 dp.sql
然后打开终端进入mysql,然后将数据库内容复制到云服务器mysql中
进入终端mysql命令: mysql root -u -p


2.>微调页面 --- 使 websocket 建立连接的 url 进行调整


3.> 从IDEA 将文件进行打包 ---- 使用 Maven的打包工具进行打包

然后将打包好的文件直接拖到服务器中即可

4.>运行程序,然后就可以使用外网进行访问
