session.hpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. #ifndef __SESSION_HPP__
  2. #define __SESSION_HPP__
  3. #include "online.hpp"
  4. #include "logger.hpp"
  5. #include <functional>
  6. typedef enum {
  7. UNLOGIN,
  8. LOGIN
  9. } ss_statu;
  10. /*用户session信息管理模块 -- 用于http短连接通信情况下用户状态的管理(登录/未登录)*/
  11. /*session 类*/
  12. class session {
  13. public:
  14. session(uint64_t ssid) : _ssid(ssid), _statu(LOGIN) { LOG(DEBUG, "session %d:%p 被创建", _ssid, this); }
  15. ~session() { LOG(DEBUG, "session %d:%p 被删除", _ssid, this); }
  16. /*添加用户*/
  17. void add_user(uint64_t uid) { _uid = uid; }
  18. /*获取用户id*/
  19. uint64_t get_user() { return _uid; }
  20. /*获取用户状态(检查用户是否已登录)*/
  21. bool is_login() { return _statu == LOGIN; }
  22. /*获取session id*/
  23. uint64_t get_ssid() { return _ssid; }
  24. /*设置session定时删除任务*/
  25. void set_timer(const wsserver_t::timer_ptr &tp) { _tp = tp; }
  26. /*获取session关联的定时器*/
  27. wsserver_t::timer_ptr& get_timer() { return _tp; }
  28. private:
  29. uint64_t _ssid; // session id
  30. uint64_t _uid; // session对应的用户id
  31. ss_statu _statu; // 用户状态(登录/未登录)
  32. wsserver_t::timer_ptr _tp; // session关联的定时器
  33. };
  34. #define SESSION_TIMEOUT 30000 //30s
  35. #define SESSION_FOREVER -1
  36. /*使用智能指针来管理session信息*/
  37. using session_ptr = std::shared_ptr<session>;
  38. /*session 管理类*/
  39. class session_manager {
  40. public:
  41. session_manager(wsserver_t *server)
  42. : _server(server), _next_ssid(1) {
  43. LOG(DEBUG, "用户session管理模块初始化成功");
  44. }
  45. ~session_manager() { LOG(DEBUG, "用户session管理模块已被销毁"); }
  46. /*为指定用户创建session信息并返回*/
  47. session_ptr create_session(uint64_t uid) {
  48. std::unique_lock<std::mutex> lock(_mutex);
  49. // 创建session信息
  50. session_ptr ssp(new session(_next_ssid));
  51. ssp->add_user(uid);
  52. // 建立sessionID与session信息的关联关系
  53. _sessions[_next_ssid] = ssp;
  54. // 更新下一个session的id计数
  55. ++_next_ssid;
  56. return ssp;
  57. }
  58. /*通过sessionID获取session信息*/
  59. session_ptr get_session_by_ssid(uint64_t ssid) {
  60. std::unique_lock<std::mutex> lock(_mutex);
  61. auto it = _sessions.find(ssid);
  62. if(it == _sessions.end()) return session_ptr();
  63. return _sessions[ssid];
  64. }
  65. /*删除session信息*/
  66. void remove_session(uint64_t ssid) {
  67. std::unique_lock<std::mutex> lock(_mutex);
  68. _sessions.erase(ssid);
  69. }
  70. /*重新添加因cancel函数被删除的_sessions成员*/
  71. void append_session(session_ptr ssp) {
  72. std::unique_lock<std::mutex> lock(_mutex);
  73. _sessions.insert(make_pair(ssp->get_ssid(), ssp)); // _sessions[ssp->get_ssid()] = ssp;
  74. }
  75. /*设置session过期时间(毫秒)*/
  76. /*基于websocketpp定时器(timer_ptr)来完成对session生命周期的管理*/
  77. void set_session_expire_time(uint64_t ssid, int ms) {
  78. //当客户端与服务器建立http短连接通信(登录/注册)时,session应该是临时的,需要设置定时删除任务
  79. //当客户端与服务器建立websocket长连接通信(游戏大厅/游戏房间)时,session应该是永久的,直到websocket长连接断开
  80. session_ptr ssp = get_session_by_ssid(ssid);
  81. if(ssp.get() == nullptr) return;
  82. // 获取session状态 -- session对象创建时默认没有关联time_ptr,此时session是永久存在的(timer_ptr==nullptr)
  83. wsserver_t::timer_ptr tp = ssp->get_timer();
  84. // 1. 在session永久的情况下设置永久
  85. if(tp.get() == nullptr && ms == SESSION_FOREVER) return;
  86. // 2. 在session永久的情况下设置定时删除任务
  87. else if(tp.get() == nullptr && ms != SESSION_FOREVER) {
  88. wsserver_t::timer_ptr tp_task = _server->set_timer(ms, std::bind(&session_manager::remove_session, this, ssid));
  89. ssp->set_timer(tp_task); // 重新设置session关联的定时器
  90. }
  91. // 3. 在session定时删除的情况下设置永久(删除定时任务)
  92. else if(tp.get() != nullptr && ms == SESSION_FOREVER) {
  93. // 注意:websocketpp使用cancel函数删除定时任务会导致定时任务直接被执行,所以我们需要重新向_sessions中添加ssid与session_ptr
  94. // 同时,由于这个定时任务不是立即被执行的(服务器处理时才处理这个任务),所以我们不能在cancel函数后面直接重新添加session_ptr(这样可能出现先添加、再删除的情况)
  95. // 而是需要专门设置一个定时器来添加ssid与session_ptr
  96. tp->cancel();
  97. // 通过定时器来添加被删除的_sessions成员
  98. _server->set_timer(0, std::bind(&session_manager::append_session, this, ssp));
  99. ssp->set_timer(wsserver_t::timer_ptr()); // 将session关联的定时器设置为空(session永久有效)
  100. }
  101. // 4. 在session定时删除的情况下重置删除时间
  102. else {
  103. // 先删除定时任务
  104. tp->cancel();
  105. _server->set_timer(0, std::bind(&session_manager::append_session, this, ssp));
  106. ssp->set_timer(wsserver_t::timer_ptr()); // 将session关联的定时器设置为空(session永久有效)
  107. // 再重新添加定时任务
  108. wsserver_t::timer_ptr tp_task = _server->set_timer(ms, std::bind(&session_manager::remove_session, this, ssid));
  109. ssp->set_timer(tp_task); // 重新设置session关联的定时器
  110. }
  111. }
  112. private:
  113. uint64_t _next_ssid; // sessionID计数器
  114. std::mutex _mutex;
  115. std::unordered_map<uint64_t, session_ptr> _sessions; // 建立ssid与session信息之间的关联关系
  116. wsserver_t *_server; // 服务器指针对象,用于设置定时任务
  117. };
  118. #endif