首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【C++】在线五子棋对战项目网页版

【C++】在线五子棋对战项目网页版

原创
作者头像
搜罗万相
发布2025-07-06 17:14:02
发布2025-07-06 17:14:02
2790
举报
文章被收录于专栏:Java开发Java开发

1.Websocket

1.1.Websocket的简单认识

WebSocket 是从 HTML5 开始支持的一种网页端和服务端保持长连接的消息推送机制。

传统的 web 程序都是属于 "⼀问⼀答" 的形式,即客户端给服务器发送了⼀个 HTTP 请求,服务器 给客⼾端返回⼀个 HTTP 响应。这种情况下服务器是属于被动的一方,在HTTP协议中,如果客⼾端不主动发起请求 ,服务器就⽆法主动给客⼾端响应

像网页即时聊天或者我们做的五子棋游戏这样的程序都是非常依赖 "消息推送" 的, 即需要服务器 主动推动消息到客户端。如果只是使用原生的 HTTP 协议,要想实现消息推送⼀般需要通过 "轮 询" 的方式实现, ⽽轮询的成本⽐较⾼并且也不能及时的获取到消息的响应。

1.2.什么是轮询呢?

比如上图,服务端是无法向主机B主动发送信息,必须让主机B先主动发送信息请求信息到服务端,问服务端有信息了吗,对于主机A也是同样如此,要想获取主机B从服务端发送的信息,服务端是不能主动发送信息到主机A,必须由主机A自己多次申请,这就是“轮询”!

基于上述两个问题, 就产⽣了WebSocket协议。WebSocket 更接近于 TCP 这种级别的通信⽅式,⼀ 旦连接建⽴完成客户端或者服务器都可以主动的向对⽅发送数据。

1.3.websocket协议切换过程

websocketpp协议是由HTTP协议切换过来的,客户端发送协议切换的请求,服务端进行响应,同意切换,这样就变成了websocket的通信连接了

1.4.websocketpp库常用接口认识

1.5.websocketpp库搭建服务器流程

实例化server对象

设置日志输出等级

初始化asio框架种的调度器

设置业务处理回调函数(具体业务处理的函数由我们自己实现)

设置服务器监听端口

开始获取新建连接

启动服务器

1.6.websocketpp库搭建服务器

代码:

#include <iostream>

#include <string>

#include <websocketpp/server.hpp>

#include <websocketpp/config/asio_no_tls.hpp>

typedef websocketpp::server<websocketpp::config::asio> wsserver_t;

void print(const std::string &str)

{

std::cout << str << std::endl;

}

void http_callback(wsserver_t *srv, websocketpp::connection_hdl hdl) {

//给客户端返回一个hello world的页面

wsserver_t::connection_ptr conn = srv->get_con_from_hdl(hdl);

std::cout << "body: " << conn->get_request_body() << std::endl;

websocketpp::http::parser::request req = conn->get_request();

std::cout << "method: " << req.get_method() << std::endl;

std::cout << "uri: " << req.get_uri() << std::endl;

std::string body = "<html><body><h1>Hello World</h1></body></html>";

conn->set_body(body);

conn->append_header("Content-Type", "text/html");

//conn->set_body(conn->get_request_body());

conn->set_status(websocketpp::http::status_code::ok);

//wsserver_t::timer_ptr tp = srv->set_timer(5000, std::bind(print, "bitejiuyeke"));

//tp->cancel();//定时任务的取消,会导致定时任务立即被执行

}

void wsopen_callback(wsserver_t *srv, websocketpp::connection_hdl hdl) {

std::cout << "websocket握手成功!!\n";

}

void wsclose_callback(wsserver_t *srv, websocketpp::connection_hdl hdl) {

std::cout << "websocket连接断开!!\n";

}

void wsmsg_callback(wsserver_t *srv, websocketpp::connection_hdl hdl, wsserver_t::message_ptr msg) {

wsserver_t::connection_ptr conn = srv->get_con_from_hdl(hdl);

std::cout << "wsmsg: " << msg->get_payload() << std::endl;

std::string rsp = "client say: " + msg->get_payload();

conn->send(rsp, websocketpp::frame::opcode::text);

}

int main()

{

//1. 实例化server对象

wsserver_t wssrv;

//2. 设置日志等级

wssrv.set_access_channels(websocketpp::log::alevel::none);

//3. 初始化asio调度器

wssrv.init_asio();

wssrv.set_reuse_addr(true);

//4. 设置回调函数

wssrv.set_http_handler(std::bind(http_callback, &wssrv, std::placeholders::_1));

wssrv.set_open_handler(std::bind(wsopen_callback, &wssrv, std::placeholders::_1));

wssrv.set_close_handler(std::bind(wsclose_callback, &wssrv, std::placeholders::_1));

wssrv.set_message_handler(std::bind(wsmsg_callback, &wssrv, std::placeholders::_1, std::placeholders::_2));

//5. 设置监听端口

wssrv.listen(8085);

//6. 开始获取新连接

wssrv.start_accept();

//7. 启动服务器

wssrv.run();

return 0;

}

AI写代码

cpp

运行

我们想要在页面生成一个Hello World

成功生成!我们使用websocketpp协议搭建网络通信平台成功!

2.mysqlclient库-接口认识

mysql数据库的访问操作流程:

客户端初始化过程:

1.初始化mysql操作句柄

2.连接mysql服务器

3.设置客户端的字符集

4.选择想要操作的数据库

客户端对数据库中数据的操作:

新增,修改,删除,都是只要sql语句执行成功了,数据库中的数据就发生了改变,没有反馈结果

查询是不一样的,因为需要首先执行语句成功,需要将查询结果保存到本地进行访问

5.执行sql语句

一旦成功,如果是增删改,则就完毕了,

查询:

6.将查询结果保存到本地

7.获取查询结果集中的结果条数

8.遍历获取结果集中的每一条数据进行处理

9.释放结果集,避免内存泄露

10.释放MySQL操作句柄

用例代码:

#include <stdio.h>

#include <string.h>

#include <mysql/mysql.h>

#define HOST "127.0.0.1"

#define PORT 3306

#define USER "root"

#define PASS "qwer@wu.888"

#define DBNAME "gobang"

int main()

{

//1. 初始化mysql句柄

// MYSQL *mysql_init(MYSQL *mysql);

MYSQL *mysql = mysql_init(NULL);

if (mysql == NULL) {

printf("mysql init failed!\n");

return -1;

}

//2. 连接服务器

// MYSQL *mysql_real_connect(mysql, host, user, pass, dbname, port, unix_socket, flag);

if (mysql_real_connect(mysql, HOST, USER, PASS, DBNAME, PORT, NULL, 0) == NULL) {

printf("connect mysql server failed : %s\n", mysql_error(mysql));

mysql_close(mysql);

return -1;

}

//3. 设置客户端字符集

// int mysql_set_character_set(mysql, "utf8");

if (mysql_set_character_set(mysql, "utf8") != 0) {

printf("set client character failed : %s\n", mysql_error(mysql));

mysql_close(mysql);

return -1;

}

//4. 选择要操作的数据库

// int mysql_select_db(mysql, dbname)

// mysql_select_db(mysql, DBNAME);

//5. 执行sql语句

// int mysql_query(MYSQL *mysql, char *sql);

//char *sql = "insert stu values(null, '小明', 18, 53, 68, 87);";

//char *sql = "update stu set ch=ch+40 where sn=1;";

//char *sql = "delete from stu where sn=1;";

char *sql = "select * from stu;";

int ret = mysql_query(mysql, sql);

if (ret != 0) {

printf("%s\n", sql);

printf("mysql query failed : %s\n", mysql_error(mysql));

mysql_close(mysql);

return -1;

}

//6. 如果sql语句是查询语句,则需要保存结果到本地

// MYSQL_RES *mysql_store_result(MYSQL *mysql)

MYSQL_RES *res = mysql_store_result(mysql);

if (res == NULL) {

mysql_close(mysql);

return -1;

}

//7. 获取结果集中的结果条数

// int mysql_num_rows(MYSQL_RES *res);

// int mysql_num_fields(MYSQL_RES *res);

int num_row = mysql_num_rows(res);

int num_col = mysql_num_fields(res);

//8. 遍历保存到本地的结果集

for (int i = 0; i < num_row; i++) {

// MYSQL_ROW mysql_fetch_row(MYSQL *res);

MYSQL_ROW row = mysql_fetch_row(res);

for (int i = 0; i < num_col; i++) {

printf("%s\t", row[i]);

}

printf("\n");

}

//9. 释放结果集

mysql_free_result(res);

//10. 关闭连接,释放句柄

mysql_close(mysql);

return 0;

}

AI写代码

cpp

运行

试着插入新数据,查询结果,成功!

3.项目模块的划分:

4.项目流程图:

4.1.玩家用户角度流程图:

4.2.服务器流程结构图:

5.实用的工具模块:

5.1.日志的实现

日志宏的实现的一些前置知识:

代码:

#ifndef __M_LOGGER_H__

#define __M_LOGGER_H__

#include <stdio.h>

#include <time.h>

#define INF 0

#define DBG 1

#define ERR 2

#define DEFAULT_LOG_LEVEL INF

#define LOG(level, format, ...) do{\

if (DEFAULT_LOG_LEVEL > level) break;\

time_t t = time(NULL);\

struct tm *lt = localtime(&t);\

char buf[32] = {0};\

strftime(buf, 31, "%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__)

#endif

AI写代码

cpp

运行

5.2.mysql工具类编译与测试

这个报错是为什么?

因为我们把第一步忘记了,第一步需要创建表结构

添加表结构之后,我们再执行一遍,成功添加小黑的信息!

代码:

class mysql_util {

public:

static MYSQL *mysql_create(const std::string &host,

const std::string &username,

const std::string &password,

const std::string &dbname,

uint16_t port = 3306) {

MYSQL *mysql = mysql_init(NULL);

if (mysql == NULL) {

ELOG("mysql init failed!");

return NULL;

}

//2. 连接服务器

if (mysql_real_connect(mysql,

host.c_str(),

username.c_str(),

password.c_str(),

dbname.c_str(), port, NULL, 0) == NULL) {

ELOG("connect mysql server failed : %s", mysql_error(mysql));

mysql_close(mysql);

return NULL;

}

//3. 设置客户端字符集

if (mysql_set_character_set(mysql, "utf8") != 0) {

ELOG("set client character failed : %s", mysql_error(mysql));

mysql_close(mysql);

return NULL;

}

return mysql;

}

static bool mysql_exec(MYSQL *mysql, const std::string &sql) {

int ret = mysql_query(mysql, sql.c_str());

if (ret != 0) {

ELOG("%s\n", sql.c_str());

ELOG("mysql query failed : %s\n", mysql_error(mysql));

return false;

}

return true;

}

static void mysql_destroy(MYSQL *mysql) {

if (mysql != NULL) {

mysql_close(mysql);

}

return ;

}

};

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档