在线用户管理,是对于当前 游戏大厅 和 游戏房间 中的用户进行管理,主要是建立起用户与 WebSocket 长连接的映射关系,这个模块具有两个功能:
- 能够让程序中根据用户信息,进而找到能够与用户客户端进行通信的
WebSocket连接,进而实现与客户端的通信 - 判断⼀个用户是否在线,或者判断用户是否已经掉线
在线用户管理类的设计与实现
首先因为要用到 websocketpp 库,所以先包一下头文件,顺序用 using 将定义改短一点,这些操作我们都把它放在 util.hpp 头文件下,这样子方便后面其它文件也要用到 websocketpp 库的时候直接用,不用重复去包头文件!
// util.hpp头文件
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_no_tls.hpp>
using wsserver_t = websocketpp::server<websocketpp::config::asio>; 接着就是成员变量和接口的设计了,我们将其放到 online.hpp 头文件下,具体参考下面:
#ifndef __MY_ONLINE_H__
#define __MY_ONLINE_H__
#include "util.hpp"
#include <mutex>
#include <unordered_map>
class online_manager
{
private:
std::unordered_map<uint64_t, wsserver_t::connection_ptr> _hall_user; // 用于建立游戏大厅用户的ID与websocket通信连接的关系
std::unordered_map<uint64_t, wsserver_t::connection_ptr> _room_user; // 用于建立游戏房间用户的ID与websocket通信连接的关系
std::mutex _mtx; // 映射等操作需要加锁保护
public:
// websocket连接建立的时候才会加入游戏大厅&游戏房间在线用户管理
void enterHall(uint64_t uid, wsserver_t::connection_ptr& conn);
void enterRoom(uint64_t uid, wsserver_t::connection_ptr& conn);
// websocket连接断开的时候,才会移除游戏大厅&游戏房间在线用户管理
void exitHall(uint64_t uid);
void exitRoom(uint64_t uid);
// 判断当前指定用户是否在游戏大厅/游戏房间
bool isInHall(uint64_t uid);
bool isInRoom(uint64_t uid);
// 通过用户ID在游戏大厅/游戏房间用户管理中获取对应的websocket通信连接
wsserver_t::connection_ptr get_conn_from_hall(uint64_t uid);
wsserver_t::connection_ptr get_conn_from_room(uint64_t uid);
};
#endif 可以看出,与 websocket 建立长连接之后,我们是通过 wsserver_t::connection_ptr 来进行通信的,这个类的功能只是为我们后面通信操作建立起一个环境,下面我们分别来实现他们的函数体,其实非常简单,就是搭建起映射关系,就是哈希表的操作而已!
最重要就是每个操作都得加锁,如下所示:
#ifndef __MY_ONLINE_H__
#define __MY_ONLINE_H__
#include "util.hpp"
#include <mutex>
#include <unordered_map>
class online_manager
{
private:
std::unordered_map<uint64_t, wsserver_t::connection_ptr> _hall_user; // 用于建立游戏大厅用户的ID与websocket通信连接的关系
std::unordered_map<uint64_t, wsserver_t::connection_ptr> _room_user; // 用于建立游戏房间用户的ID与websocket通信连接的关系
std::mutex _mtx; // 映射等操作需要加锁保护
public:
// websocket连接建立的时候才会加入游戏大厅&游戏房间在线用户管理
void enterHall(uint64_t uid, wsserver_t::connection_ptr& conn)
{
std::unique_lock<std::mutex> lock(_mtx);
_hall_user[uid] = conn;
}
void enterRoom(uint64_t uid, wsserver_t::connection_ptr& conn)
{
std::unique_lock<std::mutex> lock(_mtx);
_room_user[uid] = conn;
}
// websocket连接断开的时候,才会移除游戏大厅&游戏房间在线用户管理
void exitHall(uint64_t uid)
{
std::unique_lock<std::mutex> lock(_mtx);
_hall_user.erase(uid);
}
void exitRoom(uint64_t uid)
{
std::unique_lock<std::mutex> lock(_mtx);
_room_user.erase(uid);
}
// 判断当前指定用户是否在游戏大厅/游戏房间
bool isInHall(uint64_t uid)
{
std::unique_lock<std::mutex> lock(_mtx);
auto ret = _hall_user.find(uid);
if(ret == _hall_user.end())
return false;
return true;
}
bool isInRoom(uint64_t uid)
{
std::unique_lock<std::mutex> lock(_mtx);
auto ret = _room_user.find(uid);
if(ret == _room_user.end())
return false;
return true;
}
// 通过用户ID在游戏大厅/游戏房间用户管理中获取对应的websocket通信连接
wsserver_t::connection_ptr get_conn_from_hall(uint64_t uid)
{
std::unique_lock<std::mutex> lock(_mtx);
auto ret = _hall_user.find(uid);
if(ret == _hall_user.end())
return wsserver_t::connection_ptr();
return ret->second;
}
wsserver_t::connection_ptr get_conn_from_room(uint64_t uid)
{
std::unique_lock<std::mutex> lock(_mtx);
auto ret = _room_user.find(uid);
if(ret == _room_user.end())
return wsserver_t::connection_ptr();
return ret->second;
}
};
#endif