我做网站啦 圆通导航/14个seo小技巧
项目介绍
本项⽬主要实现⼀个⽹⻚版的五⼦棋对战游戏,其主要⽀持以下核⼼功能:
• 用户管理:实现用户注册,用户登录、获取用户信息、用户天梯分数记录、用户比赛场次记录等。
• 匹配对战:实现两个玩家在网页端根据天梯分数匹配游戏对⼿,并进行五子棋游戏对战的功能。
• 聊天功能:实现两个玩家在下棋的同时可以进⾏实时聊天的功能。
程序截图
开发环境
• Linux (Centos-7.6)
• VSCode/Vim
• g++/gdb
• Makefile
核心技术
• HTTP/WebSocket
• Websocket++
• JsonCpp
• Mysql
• C++11
• BlockQueue
• HTML/CSS/JS/AJAX
项目大流程
• 环境搭建(在Linux环境下安装需要用到的的工具以及第三方库)
• 框架设计
• 前置知识的了解
• 模块开发
配置开发环境
项目框架
项目期望:用户访问服务器获取注册页面,通过注册页面注册账号,注册成功后在登录页面进行登录。登录成功后进入游戏大厅,在游戏大厅中进行匹配对战,匹配成功,将进入游戏房间内与对手进行实时对战和实时聊天。
用户访问服务器获取的注册页面、登录页面、游戏大厅页面和游戏房间页面,属于静态资源请求。进行注册请求、登录请求、进入游戏大厅后展示个人信息的个人信息请求、匹配对战请求和下棋聊天请求属于动态功能请求。
服务器流程图:
模块解析
在项目中,需要用到6个模块,分别是:
数据管理模块:基于mysql数据库进行数据管理以及封装数据管理模块实现数据库访问。
在数据管理模块中,需要实现的功能有:注册新用户功能、登录验证功能、通过用户名获取用户信息功能、通过用户id获取用户信息功能,以及对战胜利和失败后,对数据的更新功能。
网络服务器模块:基于websocketpp库搭建websocket服务器,实现与客户端网络通信。
早网络服务器模块中,websocketpp支持http协议和websocket协议,需要实现的是http请求处理回调函数和websocket请求处理回调函数。其中,HTTP请求的处理回调函数包含了静态资源请求处理、用户注册请求处理、用户登录请求处理和用户信息请求处理。websocket请求处理回调函数包含游戏大厅、游戏房间等长连接的请求处理。
session管理模块:封装session管理,实现http客户端通信状态的维护及身份识别。
session管理模块是用于在浏览器中保存用户的通信状态和身份识别的,当用户在注册或登录后,进入了游戏大厅或游戏房间,那么将会永久保存其Cookie,当用户断开连接后,在一定的时间内,他的Cookie就会被销毁,在登录时需要重新输入账号密码。
在线用户管理模块:对于进入游戏大厅&游戏房间的长连接通信进行管理,实现随时能够获取客户端连接进行消息的主动推送。
在线用户管理模块的作用是将用户id与游戏大厅或游戏房间连接起来,在建立了websocket长连接后,将玩家加入到游戏大厅或游戏房间。当游戏结束,将玩家从游戏房间移除,当玩家退出客户端后,websocket连接断开,将玩家从游戏大厅移除。除此之外,还需要实现判断用户是否在线,即在游戏大厅中或游戏房间中,还需要通过玩家用户id去获取游戏大厅/游戏房间管理对应的通信连接。
游戏房间管理:对于同一个房间中的用户及动作进行处理(对战匹配,下棋,聊天,退出)。
在游戏房间中,游戏房间包含了房间id,玩家数量,房间状态、黑棋白棋玩家的id,以及棋盘,在线用户管理和数据模块管理的指针等字段。在游戏房间中,需要实现的是下棋的动作、处理下棋动作、处理聊天动作和处理玩家退出房间的动作,以及将动作处理广播给房间的所有玩家的方法。
游戏房间管理是需要实现的是对房间的管理,因此需要一个房间的计数器、需要实现的是创建一个游戏房间,通过房间id获取房间信息,通过用户id获取所在的房间的信息,删除房间等方法。
对战匹配管理:将所有玩家根据分数进行等级划分,进行不同等级的对战匹配。
匹配对战分有三个段位:普通、高手和大神三种段位,分别使用三个匹配队列进行玩家的匹配队列的进入等待,并且使用三个线程,异步高效地处理三种玩家的匹配对战。
对于匹配队列来说,不是使用队列,而是使用双向链表来作为匹配队列。匹配队列需要的功能是:出队入队、阻塞线程、移除指定元素等功能。
对于匹配队列的管理,需要实现将玩家进行入队,出队等操作。
将6个模块整合起来,在服务器中进行业务处理:通过网络通信获取到客户端的请求,提供不同的业务处理。
前置知识的学习:
1.websocketpp的学习和使用。
本项目中,使用websocketpp来搭建服务器,因为websocketpp同时支持http和websocket。在本项目中,HTTP用于注册、登录等服务请求中提供短链接服务。而websocket用于在游戏大厅或游戏房间中,提供长连接,并且服务器主动发送消息给客户端的服务。下面链接是关于websocket的介绍以及使用websocketpp搭建简单服务器的框架:
websocket协议
我在做项目时的难点:①HTTP请求响应和websocket请求响应的区别。②服务器搭建流程。③为什么连接句柄是使用lib::weak_ptr管理起来,而不是使用lib::shared_ptr来管理。
解决:
①TTP请求响应和websocket请求响应的区别:
HTTP请求回调处理函数主要是处理来自客户端的HTTP请求,它从连接对象中获取HTTP请求的正文,并通过请求对象获取URI和方法等信息,然后根据不同的方法和URI来进行相应的处理,最后构建HTTP响应对象并发送回客户端。HTTP是一种无状态协议,每个请求都是独立的。
WebSocket消息处理回调函数主要是处理来自客户端的WebSocket消息,它从连接对象中获取WebSocket消息的内容,并进行相应的处理逻辑。不像HTTP请求那样需要获取URI和方法等信息,WebSocket是一种双向通信协议,服务器和客户端可以在持久连接上进行实时双向通信。这个回调函数通过使用连接对象的 send 方法直接将响应消息发送回客户端。
②服务器搭建流程:先实例化出websocketpp的server类对象,通过server类对象设置日志等级、调度器、四种处理回调函数、进入监听状态、获取客户端新连接,最后启动服务器。
③为什么连接句柄是使用lib::weak_ptr管理起来,而不是使用lib::shared_ptr来管理。
hdl是wssrv.start_accept()创建出来的连接对象的引用,他们两者会有互相引用的关系,如果使用了lib::weak_ptr来管理hdl,就不会发生内存泄漏。
MySQLClient库
JsonCpp
模块开发
数据库代码
数据库设计这边,玩家的信息包含了玩家的用户id、用户名、用户密码、天梯分数、排位总场次和胜场总场次。其中,用户id作为主键,并且是自增长的,而用户名和用户密码不能为空,且用户名唯一。根据这个需求,写出以下代码:
drop database if exists online_gobang;
create database if not exists online_gobang;
use online_gobang;
create table if not exists user(id int primary key auto_increment comment '用户id',username varchar(32) unique key not null comment '用户名',password varchar(128) not null comment '用户密码',score int comment '分数',total_count int comment '总场次',win_count int comment '胜利场次'
);
日志打印
#ifndef _M_LOGGER_H_
#define _M_LOGGER_H_
#include<stdio.h>
#include<time.h>//正常
#define INF 0
//调试信息
#define DBG 1
//错误信息
#define ERR 2//strftime:将时间转换为指定格式的字符串
#define LOG(level,format,...) do{\time_t t = time(NULL);\struct tm *lt = localtime(&t);\char buf[32];\strftime(buf,21,"%H:%M:%S",lt);\fprintf(stdout,"[%s %s:%d] " format "\n",buf,__FILE__,__LINE__,##__VA_ARGS__);\
}while(0)#define ILOG(format,...) LOG(INF,format,##__VA_ARGS__);
#define DLOG(format,...) LOG(DBG,format,##__VA_ARGS__);
#define ELOG(format,...) LOG(ERR,format,##__VA_ARGS__);
工具类模块开发
工具类模块开发代码
数据管理模块开发
数据管理模块开发代码
在测试代码的时候,发现插入的数据长度太长,也就是密码在被加密之后,长度超过了我原本设置的password varchar(32)。因此,我需要将其改成varchar(128),并且重新导入:
[wjmhlh@VM-12-9-centos myspace]$ mysql -uroot -p < online_gobang.sql --重新导入
Enter password:
[wjmhlh@VM-12-9-centos myspace]$ mysql -uroot -p
Enter password: Database changed
mysql> desc user;
+-------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| username | varchar(32) | NO | UNI | NULL | |
| password | varchar(128) | NO | | NULL | |
| score | int(11) | YES | | NULL | |
| total_count | int(11) | YES | | NULL | |
| win_count | int(11) | YES | | NULL | |
+-------------+--------------+------+-----+---------+----------------+
6 rows in set (0.00 sec)mysql> select * from user;
+----+----------+-------------------------------------------+-------+-------------+-----------+
| id | username | password | score | total_count | win_count |
+----+----------+-------------------------------------------+-------+-------------+-----------+
| 1 | xiaoming | *E56A114692FE0DE073F9A1DD68A00EEB9703F3F1 | 1000 | 0 | 0 |
+----+----------+-------------------------------------------+-------+-------------+-----------+
1 row in set (0.00 sec)
在线用户管理模块开发
在线用户管理模块开发代码
在实现代码中,需要注意的是,当websocket的长连接断开后,我在移除游戏大厅或游戏房间的在线用户管理的uid时,而由于是使用unordered_map作为容器,因此与之对应的通信连接conn就会失去一个映射关系,而通信连接使用了uinque_ptr进行管理,计数器直接减为0,这个通信连接就会自动销毁。
房间管理模块开发
房间管理模块开发代码
session管理模块开发
session管理模块开发
游戏对战匹配模块开发
匹配对战模块开发代码
服务器网络通信模块开发
服务器网络通信模块开发
项目总结
1. 为什么做这个项目
为什么做这个C++五子棋对战网页版的项目,我总结了三点:
①我学习了网络编程,比如HTTP、socket编程等,还没有通过项目实践过,开发经验不足,因此我需要做一个关于网络通信连接的项目来加深我对网络编程的理解和使用。
②我是学习C++的一名计算机专业的学生,对自己掌握的C++的程度,需要有项目的实践操作去检验自己的学习成果。
③在之前学习计算机技术,实践都是通过从一些做题网站中,去做题目来检验自己对知识的掌握,以及写代码的能力,但是却没有过去写一个项目来检验自己的代码逻辑和写代码的能力的,而这个项目的开发,能够很好地检验我自己的代码逻辑和写代码的能力。
2. 项目中都用到了那些技术
在项目中,主要运用到了websocket协议和HTTP协议,以及C++11中的一些新特性,比如包装器,bing方法,互斥锁、智能指针等等,还有就是使用到了STL,比如vector、list、unordered_map等,以及是g++/gcc,makefile,vim/vscode等。
3. 讲一下项目都有那些功能,大概是怎么实现的
在线五子棋对战网页版,主要的功能有:让用户通过浏览器访问服务器,从而实现用户注册,用户登录,对战匹配,实时对战和实时聊天功能。
实现的大概思路是:
实现了6个模块,第一个模块是数据管理模块,这个模块是基于MySQL数据库进行数据管理,并且封装了MySQL的C语言接口,来进行数据管理。第二个模块是在线用户管理模块,这个模块对于进入了的游戏大厅和游戏房间的长连接通信进行管理,通过用户的uid与相对于的客户端的通信连接建立起映射关系,服务器可以实现随时获取客户端通信连接进行消息的主动推送。第三个模块是房间管理模块,在这个模块里面,先是实现了房间类,在房间类中,实现了下棋、聊天等动作,而再实现了一个房间管理的类,通过房间的管理,可以进行房间的创建、销毁、通过用户的id获取房间信息,通过房间id获取房间信息等功能。第四个模块是session模块,这个模块封装了session的管理,实现了HTTP通信连接中客户端通信状态的维护和登录或进入游戏大厅或游戏房间时进行身份识别。第五个模块是游戏对战匹配模块,在这个模块里面是将所有玩家根据分数吗,进行了档次的划分,使用多线程,分别对同档次的玩家进行不同的对战匹配。第六个模块是网络服务器的模块开发,在这个模块里面,是基于了websocketpp来搭建了服务器,实现了与客户端进行通信的功能。
4. 做的时候遇到过什么问题,当时是怎么想的,最后是怎么解决的
在做项目的过程中,遇到了不少的技术问题。
①比如在使用websocketpp协议的时候,一开始的时候没有掌握好HTTP协议和websocket协议的使用,比如说在接受请求和发送响应,它们是有区别的。一开始以为在响应的时候,需要获取uri和方法,然后根据uri和方法将那些响应的。然后当时在网上查了文档,别人写的文章,还问了一些类似chargpt的ai,最后才发现,原来websocket不需要获取请求中的uri,可以直接通过send方法给客户端做出响应。
②一开始在设计user表的时候,我把密码的长度设置了32个字符长度。开始的时候,我给用户注册密码都是6位,我没弄清楚为什么在报错的时候,提示我是密码长度超出了设置的长度。于是我在MySQL的客户端上,重新查看了describe user命令查看了表结构,发现是32位,然后我于是通过SHOW VARIABLES LIKE 'validate_password%'命令,去查看密码等级的设置,并没有出现设置不匹配的原因,后来我查了很多资料,问了老师,才知道,是在密码加密之后,密码长度会变长,于是我就设置成128位。
5. 项目中最难的一个知识点
我认为,在这个项目中最难的一个知识点是对于如何去使用websocketpp去搭建服务器这个点上。因为在做这个项目之前,我都只用过HTTP去做过一个简单的服务器,没有拓展到去学习websocket协议,从而使用websocket去搭建一个拥有HTTP协议和websocket协议的服务器。
6. 有想过怎么扩展吗
想过给下棋玩家设置一个时间限制,在规定时间内没有下棋动作,那么就直接轮到对方下棋。
还有就是增加一个AI选手,可以让玩家与AI进行对战。
项目整体代码链接
代码链接
相关文章:

C++项目:在线五子棋对战(网页版)
项目介绍 本项⽬主要实现⼀个⽹⻚版的五⼦棋对战游戏,其主要⽀持以下核⼼功能: • 用户管理:实现用户注册,用户登录、获取用户信息、用户天梯分数记录、用户比赛场次记录等。 • 匹配对战:实现两个玩家在网页端根据天梯分数匹配游戏对⼿&…...

flutter遇到的小问题记录
flutter-getx的Get.bottomSheet组件改变高度 Get.bottomSheet( isScrollControlled: true,) isScrollControlled: true 就是控制高度 (无语) 截取视频第一针 返回的是本地url 或者Uint8List的数据 String? videoStr await VideoThumbnail.thumbnailFile(video: videoPath,…...

Golang bitset 基本使用
安装: go get github.com/bits-and-blooms/bitset下面代码把fmtx换成fmt就行 //------------基本操作------------//构建一个64bit长度的bitsetb : bitset.New(64)//放入一个数b.Set(10)fmtx.Println("add-10:", b.DumpAsBits()) // 0000000…...

sql 分组讨论,二级分组(非2个字段分组),使用 窗口函数和普通分组实现
1. 二级分组需求 先按照一个字段分组,在按照 第二个字段分组。之后,如果 这个 二级分组中的数据,是 > 1条的。就筛选出来。 比如: 先按照 站点分组,再按照 设备分组, 即:如果站点上配置了…...

业务中如何过滤敏感词
在我们访问网站的时候,如果发现我们发布的内容有色情暴力的东西等等,会屏蔽掉,这种行为就是过滤敏感词。 从技术层面实现起来,其实比较简单,因为我们输入的内容就是一个大型的字符串,我们要调用某些api来判…...

用服务器搭建网站需要做什么
网站建设是一个广义的术语,涵盖了许多不同的技能和学科中所使用的生产和维护的网站。不同领域的网页设计,网页图形设计,界面设计,创作,其中包括标准化的代码和专有软件,用户体验设计和搜索引擎优化。许多人…...

clickhouse 删除操作
OLAP 数据库设计的宗旨在于分析适合一次插入多次查询的业务场景,市面上成熟的 AP 数据库在更新和删除操作上支持的均不是很好,当然 clickhouse 也不例外。但是不友好不代表不支持,本文主要介绍在 clickhouse 中如何实现数据的删除,…...

C 语言中,「.」与「->」有什么区别?
使用“.”的话,只需要声明一个结构体。格式是结构体类型名结构体名。然后通过结构体名加上“.”再加上域名,就可以引用结构体的域了。因为结构体的内存是自动分配的,就像使用int a;一样。而使用“->”的话,需要声明一个结构体的…...

github pages 用法详解 发布自己的网站
github pages 基础用法 URL 规则 假设你的 github 帐号为 mygithub,需要发布的仓库名为 myrepo,那么 pages 的 URL 为: https://mygithub.github.io/myrepo 添加内容 用任意编辑器写好(或者生成)标准的网页内容&a…...

坤简炫酷的JQuery轮播图插件
介绍: 找到了一个炫酷的JQuery轮播图插件,只需要配置三四行代码就可以实现很多二维三维炫酷的切换效果。 视频效果及教程: https://www.bilibili.com/video/BV1Fu4y1d776/ 代码: https://github.com/w-x-x-w/AwesomeWeb 使用…...

C# 条件编译
C# 条件编译 C# 条件编译:根据不同的需求,编译生成不同的程序版本,条件编译是一种编译预处理命令,它是在编译代码之前对源代码进行处理。它可以根据条件,决定是否编译某段代码 条件编译的三种形式: 第一种…...

IntelliJ IDEA如何重新弹出git身份验证窗口
1、点击File菜单—>点击Settings—>点击Appearance & Behavior—>点击System Settings—>点击Passwords—>选中Do not save, forget passwords after restart—>点击Apply—>点击OK,如下所示: 2、重启IntelliJ IDEA—>通过g…...

【雕爷学编程】Arduino动手做(200)---WS2812B幻彩LED灯带4
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的&#x…...

【雕爷学编程】Arduino动手做(201)---DFRobot 行空板03
37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的&#x…...

Spring中Bean的“一生”(生命周期)
文章目录 一、图解二、文字解析总结 一、图解 >注:处于同一行的执行顺序是从左往右 二、文字解析 SpringBean的生命周期总体分为四个阶段:实例化>属性注入>初始化>销毁 Step1 实例化Bean:根据配置文件中Bean的定义,…...

安卓:LitePal操作数据库
目录 一、LitePal介绍 常用方法: 1、插入数据: 2、更新数据: 3、删除数据: 4、查询数据: 二、LitePal的基本用法: 1、集成LitePal: 2、创建LitePal配置文件: 3、创建模型类…...

【JavaEE初阶】了解JVM
文章目录 一. JVM内存区域划分二. JVM类加载机制2.1 类加载整体流程2.2 类加载的时机2.3 双亲委派模型(经典) 三. JVM垃圾回收机制(GC)3.1 GC实际工作过程3.1.1 找到垃圾/判定垃圾1. 引用计数(不是java的做法,Python/PHP)2. 可达性分析(Java的做法) 3.1.2 清理垃圾1. 标记清除2…...

基于vue2.0和elementUi的vue农历日期组件vue-jlunar-datepicker(插件)
vue-jlunar-datepicker(插件) vue实现农历日历插件——vue-jlunar-datepicker插件 这个插件本身是基于vue2.0和elementUi框架来实现的。 安装 vue-jlunar-datepicker 插件 npm install vue-jlunar-datepicker --save // 如果安装过程中,出现…...

Python爬虫——selenium_元素定位
元素定位:自动化要做的就是模拟鼠标和键盘来操作这些元素,点击,输入等等。操作这些元素前首先要找到它们,WebDriver提供很多定位元素的方法 from selenium import webdriver# 创建浏览器对象 path files/chromedriver.exe brows…...

短视频内容平台(如TikTok、Instagram Reel、YouTube Shorts)的系统设计
现在,短视频内容已成为新趋势,每个人都在从TikTok、Instagram、YouTube等平台上消费这些内容。让我们看看如何为TikTok创建一个系统。 这样的应用程序看起来很小,但在后台有很多事情正在进行。以下是相关的挑战: •由于该应用程序…...

【git】Git 回退到指定版本:
文章目录 方法一: 使用 git reset 命令方法二:使用 git revert 命令方法三:使用 git checkout 命令常见的错误及其解决办法如下: 方法一: 使用 git reset 命令 命令可以将当前分支的 HEAD 指针指向指定的提交,从而回退代码到指定版…...

kibana+nginx配置密码 ubuntu
JAVA进阶之路-nginx设置密码 Kibana——通过Nginx代理Kibana并实现登陆认证 需要配置一下nginx文件 nginx配置文件详解 密码生成安装软件 apt install apache2-utils...

Git仓关联多个远程仓路径
前言 Git仓如果需要将代码push到多个仓,常用的做法是添加多个远程仓路径,然后分别push。这样虽然可以实现目的,但是需要多次执行push指令,很麻烦。 本文介绍关联多个远程仓路径且执行一次push指令的方法:git remote …...

使用ffmpeg将m4a及wav等文件转换为MP3格式
要使用ffmpeg将m4a及wav等文件转换为MP3格式,您可以按照以下步骤进行操作: 安装 ffmpeg 确保您已经安装了ffmpeg软件。如果没有安装,请访问ffmpeg的官方网站https://ffmpeg.org/ 并按照说明进行安装。 Win10 / Win11 可以通过 winget 命令…...

【CI/CD】Git Flow 分支模型
Git Flow 分支模型 1.前言 Git Flow 模型(本文所阐述的分支模型)构思于 2010 年,也就是 Git 诞生后不久,距今已有 10 多年。在这 10 多年中,Git Flow 在许多软件团队中大受欢迎。 在这 10 多年里,Git 本身…...

SpringBoot Thymeleaf模板引擎
Thymeleaf 模板引擎 前端交给我们的页面,是html页面。如果是我们以前开发,我们需要把他们转成jsp页面,jsp好处就是当我们查出一些数据转发到JSP页面以后,我们可以用jsp轻松实现数据的显示,及交互等。 jsp支持非常强大…...

prometheus部署
一、前言 Prometheus 是一个开源的系统监控和警报工具,用于收集、存储和查询时间序列数据。它旨在提供高效的多维数据收集和查询功能,帮助用户监控其应用程序和基础设施的性能,并在出现问题时触发警报,总来得说prometheus是用来收…...

Flink-Window详细讲解-countWindow
一.countWindow和countWindowall区别 1.countWindow: 如果您使用 countWindow(5),这意味着您将数据流划分成多个大小为 5 的窗口。划分后的窗口如下: 窗口 1: [1, 2, 3, 4, 5]窗口 2: [6, 7, 8, 9, 10] 当每个窗口中的元素数量达到 5 时&…...

React 18 state 如同一张快照
参考文章 state 如同一张快照 也许 state 变量看起来和一般的可读写的 JavaScript 变量类似。但 state 在其表现出的特性上更像是一张快照。设置它不会更改已有的 state 变量,但会触发重新渲染。 设置 state 会触发渲染 可能会认为用户界面会直接对点击之类的用…...

EasyPoi导出 导入(带校验)简单示例 EasyExcel
官方文档 : http://doc.wupaas.com/docs/easypoi pom的引入: <!-- easyPoi--><dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-spring-boot-starter</artifactId><version>4.0.0</version></dep…...