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

相关文章

C++实现回文串判断的两种高效方法

《C++实现回文串判断的两种高效方法》文章介绍了两种判断回文串的方法:解法一通过创建新字符串来处理,解法二在原字符串上直接筛选判断,两种方法都使用了双指针法,文中通过代码示例讲解的非常详细,需要的朋友... 目录一、问题描述示例二、解法一:将字母数字连接到新的 string思路代码实现代码解释复杂度分析三、

Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)

《Vue项目的甘特图组件之dhtmlx-gantt使用教程和实现效果展示(推荐)》文章介绍了如何使用dhtmlx-gantt组件来实现公司的甘特图需求,并提供了一个简单的Vue组件示例,文章还分享了一... 目录一、首先 npm 安装插件二、创建一个vue组件三、业务页面内 引用自定义组件:四、dhtmlx

Node.js net模块的使用示例

《Node.jsnet模块的使用示例》本文主要介绍了Node.jsnet模块的使用示例,net模块支持TCP通信,处理TCP连接和数据传输,具有一定的参考价值,感兴趣的可以了解一下... 目录简介引入 net 模块核心概念TCP (传输控制协议)Socket服务器TCP 服务器创建基本服务器服务器配置选项服

SpringBoot项目注入 traceId 追踪整个请求的日志链路(过程详解)

《SpringBoot项目注入traceId追踪整个请求的日志链路(过程详解)》本文介绍了如何在单体SpringBoot项目中通过手动实现过滤器或拦截器来注入traceId,以追踪整个请求的日志链... SpringBoot项目注入 traceId 来追踪整个请求的日志链路,有了 traceId, 我们在排

C++一个数组赋值给另一个数组方式

《C++一个数组赋值给另一个数组方式》文章介绍了三种在C++中将一个数组赋值给另一个数组的方法:使用循环逐个元素赋值、使用标准库函数std::copy或std::memcpy以及使用标准库容器,每种方... 目录C++一个数组赋值给另一个数组循环遍历赋值使用标准库中的函数 std::copy 或 std::

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

使用C++实现链表元素的反转

《使用C++实现链表元素的反转》反转链表是链表操作中一个经典的问题,也是面试中常见的考题,本文将从思路到实现一步步地讲解如何实现链表的反转,帮助初学者理解这一操作,我们将使用C++代码演示具体实现,同... 目录问题定义思路分析代码实现带头节点的链表代码讲解其他实现方式时间和空间复杂度分析总结问题定义给定

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤

C++初始化数组的几种常见方法(简单易懂)

《C++初始化数组的几种常见方法(简单易懂)》本文介绍了C++中数组的初始化方法,包括一维数组和二维数组的初始化,以及用new动态初始化数组,在C++11及以上版本中,还提供了使用std::array... 目录1、初始化一维数组1.1、使用列表初始化(推荐方式)1.2、初始化部分列表1.3、使用std::

C++ Primer 多维数组的使用

《C++Primer多维数组的使用》本文主要介绍了多维数组在C++语言中的定义、初始化、下标引用以及使用范围for语句处理多维数组的方法,具有一定的参考价值,感兴趣的可以了解一下... 目录多维数组多维数组的初始化多维数组的下标引用使用范围for语句处理多维数组指针和多维数组多维数组严格来说,C++语言没