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

文章介绍了在Web开发中如何通过HTTP协议的会话机制,利用session对象存储用户状态信息,并详细阐述了session的创建、管理、过期时间和与WebSocket定时器的集成,以实现用户登录状态的持久化和会话的生命周期控制。
摘要由CSDN通过智能技术生成

零、前置

在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对应的用户ID
        ss_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对应的用户ID
        ss_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管理器即将销毁!"); }
        // 创建一个session
        session_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;
        }

        // 添加一个已有的session
        void append_session(const session_ptr &ssp) {
            std::unique_lock<std::mutex> lock(_mutex);
            _session.insert(std::make_pair(ssp->ssid(), ssp));
        }
        // 获取一个session
        session_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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值