2.7.C++项目:网络版五子棋对战之session模块的设计

2023-10-25 04:04

本文主要是介绍2.7.C++项目:网络版五子棋对战之session模块的设计,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 零、前置
  • 一、意义
  • 二、功能
  • 三、管理
  • 四、框架
  • 五、完整代码

零、前置

在WEB开发中,HTTP协议是⼀种无状态短链接的协议,这就导致⼀个客户端连接到服务器上之后,服务器不知道当前的连接对应的是哪个用户,也不知道客户端是否登录成功,这时候为客户端提所有服务是不合理的。

在这里插入图片描述

因此,服务器为每个用户浏览器创建⼀个会话对象(session对象)。
注意:⼀个浏览器独占⼀个session对象(默认情况下)。因此,在需要保护用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,识别该连接对应的用户,并为用户提供服务。
在这里插入图片描述

一、意义

保存客户端的用户状态信息。

二、功能

  1. 有自己的表示:ssid
  2. 用户的状态信息

三、管理

session管理:
// 1. 创建session
// 2. 为session设置过期时间
// 3. 获取session
// 4. 销毁session(过期被自动销毁)

四、框架

#ifndef __M_SS_H__
#define __M_SS_H__
#include "util.hpp"
#include <unordered_map>
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_no_tls.hpp>typedef enum {UNLOGIN, LOGIN} ss_statu;
class session {private:uint64_t _ssid; //标识符uint64_t _uid; //session对应的用户IDss_statu _statu; //用户状态:未登录,已登录wsserver_t::timer_ptr _tp; //session关联的定时器public:session(uint64_t ssid): _ssid(ssid) { DLOG("SESSION %p 被创建!!", this); }~session() { DLOG("SESSION %p 被释放!!", this); }uint64_t ssid() { return _ssid; }void set_statu(ss_statu statu) { _statu = statu; }void set_user(uint64_t uid) { _uid = uid; }uint64_t get_user() { return _uid;}bool is_login() { return (_statu == LOGIN); }void set_timer(const wsserver_t::timer_ptr &tp) {_tp = tp;}wsserver_t::timer_ptr& get_timer() { return _tp; }
};

五、完整代码

// session模块:保存客户端的用户状态信息
// 1. 有自己的表示:ssid
// 2. 用户的状态信息// session管理:
// 1. 创建session
// 2. 为session设置过期时间
// 3. 获取session
// 4. 销毁session(过期被自动销毁)// websocket库中定时器的使用!
// 定时任务取消会导致定时任务立刻被执行!#ifndef __M_SS_H__
#define __M_SS_H__
#include "util.hpp"
#include <unordered_map>
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_no_tls.hpp>typedef enum {UNLOGIN, LOGIN} ss_statu;
class session {private:uint64_t _ssid; //标识符uint64_t _uid; //session对应的用户IDss_statu _statu; //用户状态:未登录,已登录wsserver_t::timer_ptr _tp; //session关联的定时器public:session(uint64_t ssid): _ssid(ssid) { DLOG("SESSION %p 被创建!!", this); }~session() { DLOG("SESSION %p 被释放!!", this); }uint64_t ssid() { return _ssid; }void set_statu(ss_statu statu) { _statu = statu; }void set_user(uint64_t uid) { _uid = uid; }uint64_t get_user() { return _uid;}bool is_login() { return (_statu == LOGIN); }void set_timer(const wsserver_t::timer_ptr &tp) {_tp = tp;}wsserver_t::timer_ptr& get_timer() { return _tp; }
};#define SESSION_TIMEOUT 30000
#define SESSION_FOREVER -1
using session_ptr = std::shared_ptr<session>;
// 管理的数据
// 1.ssid的计数器
// 2.互斥锁
// 3.管理器 unordered_map<ssid,session_ptr>
// 4.websocket 的 server 对象 —— 用于添加定时任务
class session_manager {private:uint64_t _next_ssid;std::mutex _mutex;std::unordered_map<uint64_t, session_ptr> _session;wsserver_t *_server;public:session_manager(wsserver_t *srv): _next_ssid(1), _server(srv){DLOG("session管理器初始化完毕!");}~session_manager() { DLOG("session管理器即将销毁!"); }// 创建一个sessionsession_ptr create_session(uint64_t uid, ss_statu statu) {std::unique_lock<std::mutex> lock(_mutex);session_ptr ssp(new session(_next_ssid));ssp->set_statu(statu);ssp->set_user(uid);_session.insert(std::make_pair(_next_ssid, ssp));_next_ssid++;return ssp;}// 添加一个已有的sessionvoid append_session(const session_ptr &ssp) {std::unique_lock<std::mutex> lock(_mutex);_session.insert(std::make_pair(ssp->ssid(), ssp));}// 获取一个sessionsession_ptr get_session_by_ssid(uint64_t ssid) {std::unique_lock<std::mutex> lock(_mutex);auto it = _session.find(ssid);if (it == _session.end()) {return session_ptr();}return it->second;}void remove_session(uint64_t ssid) {std::unique_lock<std::mutex> lock(_mutex);_session.erase(ssid);}// 定时删除任务void set_session_expire_time(uint64_t ssid, int ms) {// 依赖于websocketpp的定时器来完成session生命周期的管理。// 登录之后,创建session,session需要在指定时间无通信后删除// 但是进入游戏大厅,或者游戏房间,这个session就应该永久存在// 等到退出游戏大厅,或者游戏房间,这个session应该被重新设置为临时,在长时间无通信后被删除// 在http通信的时候(登录,注册) session 应该具备生命周期,指定时间无通信后删除!// 在客户端建立websocket长链结构,session应该是永久存在的!// 登录之后,创建session session需要在指定时间后无通信就删除// 但是在进入游戏大厅,或者游戏房间,这个session就应该永久存在// 但是在推出游戏大厅或者游戏房间,这个session就应该被重新设置为临时的,在长时间无通信后删除!session_ptr ssp = get_session_by_ssid(ssid);if (ssp.get() == nullptr) {return;}wsserver_t::timer_ptr tp = ssp->get_timer();// 1. 在session永久存在的情况下,设置永久存在if (tp.get() == nullptr && ms == SESSION_FOREVER) {// 1. 在session永久存在的情况下,设置永久存在return ;// 2. 在session永久存在的情况下,设置指定时间之后被删除的定时任务}else if (tp.get() == nullptr && ms != SESSION_FOREVER) {wsserver_t::timer_ptr tmp_tp = _server->set_timer(ms, std::bind(&session_manager::remove_session, this, ssid));ssp->set_timer(tmp_tp);}// 3. 在session设置了定时删除的情况下,将session设置为永久存在else if (tp.get() != nullptr && ms == SESSION_FOREVER) {// 删除定时任务--- stready_timer删除定时任务会导致任务直接被执行tp->cancel();//因为这个取消定时任务并不是立即取消的//因此重新给session管理器中,添加一个session信息, 且添加的时候需要使用定时器,而不是立即添加ssp->set_timer(wsserver_t::timer_ptr());//将session关联的定时器设置为空// 可能在添加之后又被删除_server->set_timer(0, std::bind(&session_manager::append_session, this, ssp));}// 4. 在session设置了定时删除的情况下,将session重置删除时间else {tp->cancel();//因为这个取消定时任务并不是立即取消的ssp->set_timer(wsserver_t::timer_ptr());_server->set_timer(0, std::bind(&session_manager::append_session, this, ssp));//重新给session添加定时销毁任务wsserver_t::timer_ptr tmp_tp  = _server->set_timer(ms,std::bind(&session_manager::remove_session, this, ssp->ssid()));//重新设置session关联的定时器ssp->set_timer(tmp_tp);}}
};#endif

这篇关于2.7.C++项目:网络版五子棋对战之session模块的设计的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/279901

相关文章

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名