Jelajahi Sumber

添加用户信息模块

yaozheng0922 5 bulan lalu
induk
melakukan
a292db61d9
1 mengubah file dengan 128 tambahan dan 0 penghapusan
  1. 128 0
      source/session.hpp

+ 128 - 0
source/session.hpp

@@ -0,0 +1,128 @@
+#ifndef __SESSION_HPP__
+#define __SESSION_HPP__
+#include "online.hpp"
+#include "logger.hpp"
+#include <functional>
+
+typedef enum {
+    UNLOGIN, 
+    LOGIN
+} ss_statu;
+
+/*用户session信息管理模块 -- 用于http短连接通信情况下用户状态的管理(登录/未登录)*/
+/*session 类*/
+class session {
+public:
+    session(uint64_t ssid) : _ssid(ssid), _statu(LOGIN) { LOG(DEBUG, "session %d:%p 被创建", _ssid, this); }
+    ~session() { LOG(DEBUG, "session %d:%p 被删除", _ssid, this); }
+    /*添加用户*/
+    void add_user(uint64_t uid) { _uid = uid; }
+    /*获取用户id*/
+    uint64_t get_user() { return _uid; }
+    /*获取用户状态(检查用户是否已登录)*/
+    bool is_login() { return _statu == LOGIN; }
+    /*获取session id*/
+    uint64_t get_ssid() { return _ssid; }
+    /*设置session定时删除任务*/
+    void set_timer(const wsserver_t::timer_ptr &tp) { _tp = tp; }
+    /*获取session关联的定时器*/
+    wsserver_t::timer_ptr& get_timer() { return _tp; }
+private:
+    uint64_t _ssid;             // session id
+    uint64_t _uid;              // session对应的用户id
+    ss_statu _statu;            // 用户状态(登录/未登录)
+    wsserver_t::timer_ptr _tp;  // session关联的定时器
+};
+
+#define SESSION_TIMEOUT 30000  //30s
+#define SESSION_FOREVER -1
+
+/*使用智能指针来管理session信息*/
+using session_ptr = std::shared_ptr<session>;
+
+/*session 管理类*/
+class session_manager {
+public:
+    session_manager(wsserver_t *server)
+    : _server(server), _next_ssid(1) {
+        LOG(DEBUG, "用户session管理模块初始化成功");
+    }
+    ~session_manager() { LOG(DEBUG, "用户session管理模块已被销毁"); }
+
+    /*为指定用户创建session信息并返回*/
+    session_ptr create_session(uint64_t uid) {
+        std::unique_lock<std::mutex> lock(_mutex);
+        // 创建session信息
+        session_ptr ssp(new session(_next_ssid));
+        ssp->add_user(uid);
+        // 建立sessionID与session信息的关联关系
+        _sessions[_next_ssid] = ssp;
+        // 更新下一个session的id计数
+        ++_next_ssid;
+        return ssp;
+    }
+
+    /*通过sessionID获取session信息*/
+    session_ptr get_session_by_ssid(uint64_t ssid) {
+        std::unique_lock<std::mutex> lock(_mutex);
+        auto it = _sessions.find(ssid);
+        if(it == _sessions.end()) return session_ptr();
+        return _sessions[ssid];
+    }
+
+    /*删除session信息*/
+    void remove_session(uint64_t ssid) {
+        std::unique_lock<std::mutex> lock(_mutex);
+        _sessions.erase(ssid);
+    }
+
+    /*重新添加因cancel函数被删除的_sessions成员*/
+    void append_session(session_ptr ssp) {
+        std::unique_lock<std::mutex> lock(_mutex);
+        _sessions.insert(make_pair(ssp->get_ssid(), ssp));  // _sessions[ssp->get_ssid()] = ssp;
+    }
+
+    /*设置session过期时间(毫秒)*/
+    /*基于websocketpp定时器(timer_ptr)来完成对session生命周期的管理*/
+    void set_session_expire_time(uint64_t ssid, int ms) {
+        //当客户端与服务器建立http短连接通信(登录/注册)时,session应该是临时的,需要设置定时删除任务
+        //当客户端与服务器建立websocket长连接通信(游戏大厅/游戏房间)时,session应该是永久的,直到websocket长连接断开
+        session_ptr ssp = get_session_by_ssid(ssid);
+        if(ssp.get() == nullptr) return;
+        // 获取session状态 -- session对象创建时默认没有关联time_ptr,此时session是永久存在的(timer_ptr==nullptr)
+        wsserver_t::timer_ptr tp = ssp->get_timer();
+        // 1. 在session永久的情况下设置永久
+        if(tp.get() == nullptr && ms == SESSION_FOREVER) return;
+        // 2. 在session永久的情况下设置定时删除任务
+        else if(tp.get() == nullptr && ms != SESSION_FOREVER) {
+            wsserver_t::timer_ptr tp_task = _server->set_timer(ms, std::bind(&session_manager::remove_session, this, ssid));
+            ssp->set_timer(tp_task);  // 重新设置session关联的定时器
+        }
+        // 3. 在session定时删除的情况下设置永久(删除定时任务)
+        else if(tp.get() != nullptr && ms == SESSION_FOREVER) {
+            // 注意:websocketpp使用cancel函数删除定时任务会导致定时任务直接被执行,所以我们需要重新向_sessions中添加ssid与session_ptr
+            // 同时,由于这个定时任务不是立即被执行的(服务器处理时才处理这个任务),所以我们不能在cancel函数后面直接重新添加session_ptr(这样可能出现先添加、再删除的情况)
+            // 而是需要专门设置一个定时器来添加ssid与session_ptr
+            tp->cancel();
+            // 通过定时器来添加被删除的_sessions成员
+            _server->set_timer(0, std::bind(&session_manager::append_session, this, ssp)); 
+            ssp->set_timer(wsserver_t::timer_ptr());  // 将session关联的定时器设置为空(session永久有效)
+        }
+        // 4. 在session定时删除的情况下重置删除时间
+        else {
+            // 先删除定时任务
+            tp->cancel();
+            _server->set_timer(0, std::bind(&session_manager::append_session, this, ssp)); 
+            ssp->set_timer(wsserver_t::timer_ptr());  // 将session关联的定时器设置为空(session永久有效)
+            // 再重新添加定时任务
+            wsserver_t::timer_ptr tp_task = _server->set_timer(ms, std::bind(&session_manager::remove_session, this, ssid));
+            ssp->set_timer(tp_task);  // 重新设置session关联的定时器
+        }
+    }
+private:
+    uint64_t _next_ssid;     // sessionID计数器                             
+    std::mutex _mutex;  
+    std::unordered_map<uint64_t, session_ptr> _sessions;  // 建立ssid与session信息之间的关联关系
+    wsserver_t *_server;  // 服务器指针对象,用于设置定时任务
+};
+#endif