|
@@ -0,0 +1,442 @@
|
|
|
+/*
|
|
|
+服务器模块
|
|
|
+通过对之前所有模块进行整合以及进行服务器搭建,最终封装实现出⼀个gobang_server的服务器模块类,向外提供搭建五⼦棋对战服务器的接⼝。
|
|
|
+达到通过实例化的对象就可以简便的完成服务器搭建的目的
|
|
|
+*/
|
|
|
+
|
|
|
+#ifndef __SERVER_HPP__
|
|
|
+#define __SERVER_HPP__
|
|
|
+#include "util.hpp"
|
|
|
+#include "db.hpp"
|
|
|
+#include "online.hpp"
|
|
|
+#include "room.hpp"
|
|
|
+#include "matcher.hpp"
|
|
|
+#include "session.hpp"
|
|
|
+
|
|
|
+#define WWWROOT "./wwwroot"
|
|
|
+
|
|
|
+typedef websocketpp::server<websocketpp::config::asio> wsserver_t;
|
|
|
+
|
|
|
+class gobang_server {
|
|
|
+private:
|
|
|
+ /*http静态资源请求处理函数(注册界面、登录界面、游戏大厅界面)*/
|
|
|
+ void file_handler(wsserver_t::connection_ptr conn) {
|
|
|
+ // 获取http请求对象与请求uri
|
|
|
+ websocketpp::http::parser::request req = conn->get_request();
|
|
|
+ std::string uri = req.get_uri();
|
|
|
+ // 根据uri组合出文件路径,如果文件路径是目录(/结尾)则追加login.html,否则返回相应界面
|
|
|
+ std::string pathname = _wwwroot + uri;
|
|
|
+ if(pathname.back() == '/') {
|
|
|
+ pathname += "login.html";
|
|
|
+ }
|
|
|
+ // 读取文件内容,如果文件不存在,则返回404
|
|
|
+ std::string body;
|
|
|
+ if(file_util::read(pathname.c_str(), body) == false) {
|
|
|
+ body += "<html><head><meta charset='UTF-8'/></head><body><h1> 404 Not Found </h1></body></html>";
|
|
|
+ // 设置响应状态码
|
|
|
+ conn->set_status(websocketpp::http::status_code::not_found);
|
|
|
+ }
|
|
|
+ else conn->set_status(websocketpp::http::status_code::ok);
|
|
|
+ // 添加响应头部
|
|
|
+ conn->append_header("Content-Length", std::to_string(body.size()));
|
|
|
+ // 设置响应正文
|
|
|
+ conn->set_body(body);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*处理http响应的子功能函数*/
|
|
|
+ void http_resp(wsserver_t::connection_ptr conn, bool result, websocketpp::http::status_code::value code, const std::string &reason) {
|
|
|
+ // 设置响应正文及其序列化
|
|
|
+ Json::Value resp;
|
|
|
+ std::string resp_body;
|
|
|
+ resp["result"] = result;
|
|
|
+ resp["reason"] = reason;
|
|
|
+ json_util::serialize(resp, resp_body);
|
|
|
+ // 设置响应状态码,添加响应正文以及正文类型
|
|
|
+ conn->set_status(code);
|
|
|
+ conn->append_header("Content-Type", "application/json");
|
|
|
+ conn->set_body(resp_body);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*http动态功能请求处理函数 -- 用户注册*/
|
|
|
+ void reg(wsserver_t::connection_ptr conn) {
|
|
|
+ // 获取json格式的请求正文
|
|
|
+ std::string req_body = conn->get_request_body();
|
|
|
+ // 将正文反序列化得到username和password
|
|
|
+ Json::Value user_info;
|
|
|
+ if(json_util::deserialize(req_body, user_info) == false) {
|
|
|
+ return http_resp(conn, false, websocketpp::http::status_code::bad_request, "请求正文格式错误");
|
|
|
+ }
|
|
|
+ // 数据库新增用户
|
|
|
+ if(user_info["username"].isNull() || user_info["password"].isNull()) {
|
|
|
+ return http_resp(conn, false, websocketpp::http::status_code::bad_request, "请输入用户名/密码");
|
|
|
+ }
|
|
|
+ if(_ut.registers(user_info) == false) {
|
|
|
+ return http_resp(conn, false, websocketpp::http::status_code::bad_request, "该用户名已被占用");
|
|
|
+ }
|
|
|
+ return http_resp(conn, true, websocketpp::http::status_code::ok, "用户注册成功");
|
|
|
+ }
|
|
|
+
|
|
|
+ /*http动态功能请求处理函数 -- 用户登录*/
|
|
|
+ void login(wsserver_t::connection_ptr conn) {
|
|
|
+ // 获取请求正文并反序列化
|
|
|
+ std::string req_body = conn->get_request_body();
|
|
|
+ Json::Value user_info;
|
|
|
+ if(json_util::deserialize(req_body, user_info) == false) {
|
|
|
+ return http_resp(conn, false, websocketpp::http::status_code::bad_request, "请求正文格式错误");
|
|
|
+ }
|
|
|
+ if(user_info["username"].isNull() || user_info["password"].isNull()) {
|
|
|
+ return http_resp(conn, false, websocketpp::http::status_code::bad_request, "请输入用户名/密码");
|
|
|
+ }
|
|
|
+ // 用户登录 -- 登录失败返回404
|
|
|
+ if(_ut.login(user_info) == false) {
|
|
|
+ return http_resp(conn, false, websocketpp::http::status_code::bad_request, "用户名/密码错误");
|
|
|
+ }
|
|
|
+ // 登录成功则为用户创建session信息以及session生命周期
|
|
|
+ session_ptr ssp = _sm.create_session(user_info["id"].asUInt64());
|
|
|
+ if(ssp.get() == nullptr) {
|
|
|
+ return http_resp(conn, false, websocketpp::http::status_code::internal_server_error, "用户会话创建失败");
|
|
|
+ }
|
|
|
+ _sm.set_session_expire_time(ssp->get_ssid(), SESSION_TIMEOUT);
|
|
|
+ // 设置过响应头部 将cookie返回给客户端
|
|
|
+ std::string cookie_ssid = "SSID=" + std::to_string(ssp->get_ssid());
|
|
|
+ conn->append_header("Set-Cookie", cookie_ssid);
|
|
|
+ return http_resp(conn, true, websocketpp::http::status_code::ok, "用户登录成功");
|
|
|
+ }
|
|
|
+
|
|
|
+ /*从http请求头部Cookie中获取指定key对应的value*/
|
|
|
+ bool get_cookie_val(const std::string &cookie_str, const std::string &key, std::string &val) {
|
|
|
+ // cookie_str格式:SSID=XXX; path=/XXX
|
|
|
+ // 先以逗号为分割将cookie_str中的各个cookie信息分割开
|
|
|
+ std::vector<std::string> cookies;
|
|
|
+ string_util::split(cookie_str, ";", cookies);
|
|
|
+ // 再以等号为分割将单个cookie中的key与val分割开,比对查找目标key对应的val
|
|
|
+ for(const auto cookie : cookies) {
|
|
|
+ std::vector<std::string> kv;
|
|
|
+ string_util::split(cookie, "=", kv);
|
|
|
+ if(kv.size() != 2) continue;
|
|
|
+ if(kv[0] == key) {
|
|
|
+ val = kv[1];
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*http动态功能请求处理函数 -- 获取用户信息*/
|
|
|
+ void info(wsserver_t::connection_ptr conn) {
|
|
|
+ // 通过http请求头部中的cookie字段获取用户ssid
|
|
|
+ std::string cookie_str = conn->get_request_header("Cookie");
|
|
|
+ if(cookie_str.empty()) {
|
|
|
+ return http_resp(conn, false, websocketpp::http::status_code::bad_request, "找不到Cookie信息,请重新登录");
|
|
|
+ }
|
|
|
+ std::string ssid_str;
|
|
|
+ if(get_cookie_val(cookie_str, "SSID", ssid_str) == false) {
|
|
|
+ return http_resp(conn, false, websocketpp::http::status_code::bad_request, "找不到Session信息,请重新登录");
|
|
|
+ }
|
|
|
+ // 根据ssid_str获取用户Session信息
|
|
|
+ session_ptr ssp = _sm.get_session_by_ssid(std::stol(ssid_str));
|
|
|
+ if(ssp.get() == nullptr) {
|
|
|
+ return http_resp(conn, false, websocketpp::http::status_code::bad_request, "Session已过期,请重新登录");
|
|
|
+ }
|
|
|
+ // 通过用户session获取用户id,再根据用户id获取用户详细信息
|
|
|
+ uint64_t uid = ssp->get_user();
|
|
|
+ Json::Value user;
|
|
|
+ if(_ut.select_by_id(uid, user) == false) {
|
|
|
+ return http_resp(conn, false, websocketpp::http::status_code::bad_request, "用户信息不存在");
|
|
|
+ }
|
|
|
+ // 返回用户详细信息
|
|
|
+ std::string body;
|
|
|
+ json_util::serialize(user, body);
|
|
|
+ std::string resp_cookie = "SSID=" + ssid_str;
|
|
|
+ conn->set_status(websocketpp::http::status_code::ok);
|
|
|
+ conn->append_header("Content-Type", "application/json");
|
|
|
+ conn->append_header("Set-Cookie", resp_cookie);
|
|
|
+ conn->set_body(body);
|
|
|
+ // 更新用户session过期时间
|
|
|
+ _sm.set_session_expire_time(ssp->get_ssid(), SESSION_TIMEOUT);
|
|
|
+ }
|
|
|
+private:
|
|
|
+ /*http请求回调函数*/
|
|
|
+ void http_callback(websocketpp::connection_hdl hdl) {
|
|
|
+
|
|
|
+ wsserver_t::connection_ptr conn = _wssrv.get_con_from_hdl(hdl);
|
|
|
+ websocketpp::http::parser::request req = conn->get_request();
|
|
|
+ std::string method = req.get_method();
|
|
|
+ std::string uri = req.get_uri();
|
|
|
+ // 根据不同的请求方法和请求路径类型调用不同的处理函数
|
|
|
+ // 动态功能请求
|
|
|
+ if(method == "POST" && uri == "/reg") reg(conn);
|
|
|
+ else if(method == "POST" && uri == "/login") login(conn);
|
|
|
+ else if(method == "GET" && uri == "/info") info(conn);
|
|
|
+ // 静态资源请求
|
|
|
+ else file_handler(conn);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*游戏大厅websocket长连接建立后的响应子函数*/
|
|
|
+ void game_hall_resp(wsserver_t::connection_ptr conn, bool result, const std::string &reason = "") {
|
|
|
+ Json::Value resp;
|
|
|
+ resp["optype"] = "hall_ready";
|
|
|
+ resp["result"] = result;
|
|
|
+ // 只有错误才返回错误信息reason
|
|
|
+ if(result == false) resp["reason"] = reason;
|
|
|
+ std::string body;
|
|
|
+ json_util::serialize(resp, body);
|
|
|
+ conn->send(body);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*wsopen_callback子函数 -- 游戏大厅websocket长连接建立后的处理函数*/
|
|
|
+ void wsopen_game_hall(wsserver_t::connection_ptr conn) {
|
|
|
+ // 检查用户是否登录 -- 检查cookie&session信息
|
|
|
+ // 通过http请求头部中的cookie字段获取用户ssid
|
|
|
+ std::string cookie_str = conn->get_request_header("Cookie");
|
|
|
+ if(cookie_str.empty()) {
|
|
|
+ return game_hall_resp(conn, false, "找不到Cookie信息,请重新登录");
|
|
|
+ }
|
|
|
+ std::string ssid_str;
|
|
|
+ if(get_cookie_val(cookie_str, "SSID", ssid_str) == false) {
|
|
|
+ return game_hall_resp(conn, false, "找不到Session信息,请重新登录");
|
|
|
+ }
|
|
|
+ // 根据ssid_str获取用户Session信息
|
|
|
+ session_ptr ssp = _sm.get_session_by_ssid(std::stol(ssid_str));
|
|
|
+ if(ssp.get() == nullptr) {
|
|
|
+ return game_hall_resp(conn, false, "Session已过期,请重新登录");
|
|
|
+ }
|
|
|
+ // 通过用户session获取用户id
|
|
|
+ uint64_t uid = ssp->get_user();
|
|
|
+ // 检查用户是否重复登录 -- 用户游戏大厅长连接/游戏房间长连接是否已经存在
|
|
|
+ if(_om.is_in_game_hall(uid) == true) {
|
|
|
+ return game_hall_resp(conn, false, "玩家重复登录");
|
|
|
+ }
|
|
|
+ // 将玩家及其连接加入到在线游戏大厅中
|
|
|
+ _om.enter_game_hall(uid, conn);
|
|
|
+ // 返回响应
|
|
|
+ game_hall_resp(conn, true);
|
|
|
+ // 将用户Session过期时间设置为永不过期
|
|
|
+ _sm.set_session_expire_time(ssp->get_ssid(), SESSION_FOREVER);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*游戏房间websocket长连接建立后的响应子函数*/
|
|
|
+ void game_room_resp(wsserver_t::connection_ptr conn, bool result, const std::string &reason,
|
|
|
+ uint64_t room_id = 0, uint64_t self_id = 0, uint64_t white_id = 0, uint64_t black_id = 0) {
|
|
|
+ Json::Value resp;
|
|
|
+ resp["optype"] = "room_ready";
|
|
|
+ resp["result"] = result;
|
|
|
+ // 如果成功返回room_id,self_id,white_id,black_id等信息,如果错误则返回错误信息
|
|
|
+ if(result == true) {
|
|
|
+ resp["room_id"] = (Json::UInt64)room_id;
|
|
|
+ resp["uid"] = (Json::UInt64)self_id;
|
|
|
+ resp["white_id"] = (Json::UInt64)white_id;
|
|
|
+ resp["black_id"] = (Json::UInt64)black_id;
|
|
|
+ }
|
|
|
+ else resp["reason"] = reason;
|
|
|
+ std::string body;
|
|
|
+ json_util::serialize(resp, body);
|
|
|
+ conn->send(body);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*wsopen_callback子函数 -- 游戏房间websocket长连接建立后的处理函数*/
|
|
|
+ void wsopen_game_room(wsserver_t::connection_ptr conn) {
|
|
|
+ // 获取cookie&session信息
|
|
|
+ std::string cookie_str = conn->get_request_header("Cookie");
|
|
|
+ if(cookie_str.empty()) {
|
|
|
+ return game_room_resp(conn, false, "找不到Cookie信息,请重新登录");
|
|
|
+ }
|
|
|
+ std::string ssid_str;
|
|
|
+ if(get_cookie_val(cookie_str, "SSID", ssid_str) == false) {
|
|
|
+ return game_room_resp(conn, false, "找不到Session信息,请重新登录");
|
|
|
+ }
|
|
|
+ // 根据ssid_str获取用户Session信息
|
|
|
+ session_ptr ssp = _sm.get_session_by_ssid(std::stol(ssid_str));
|
|
|
+ if(ssp.get() == nullptr) {
|
|
|
+ return game_room_resp(conn, false, "Session已过期,请重新登录");
|
|
|
+ }
|
|
|
+ // 判断用户是否已经处于游戏大厅/房间中了(在创建游戏房间长连接之前,游戏大厅的长连接已经断开了) -- 在线用户管理
|
|
|
+ if(_om.is_in_game_hall(ssp->get_user()) || _om.is_in_game_room(ssp->get_user())) {
|
|
|
+ return game_room_resp(conn, false, "玩家重复登录");
|
|
|
+ }
|
|
|
+ // 判断游戏房间是否被创建 -- 游戏房间管理
|
|
|
+ room_ptr rp = _rm.get_room_by_uid(ssp->get_user());
|
|
|
+ if(rp.get() == nullptr) {
|
|
|
+ return game_room_resp(conn, false, "找不到房间信息");
|
|
|
+ }
|
|
|
+ // 将玩家加入到在线游戏房间中
|
|
|
+ _om.enter_game_room(ssp->get_user(), conn);
|
|
|
+ // 返回响应信息
|
|
|
+ game_room_resp(conn, true, "", rp->_room_id, ssp->get_user(), rp->_white_user_id, rp->_black_user_id);
|
|
|
+ // 将玩家session设置为永不过期
|
|
|
+ _sm.set_session_expire_time(ssp->get_ssid(), SESSION_FOREVER);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*websocket长连接建立之后的处理函数*/
|
|
|
+ void wsopen_callback(websocketpp::connection_hdl hdl) {
|
|
|
+ // 获取通信连接、http请求对象和请求uri
|
|
|
+ wsserver_t::connection_ptr conn = _wssrv.get_con_from_hdl(hdl);
|
|
|
+ websocketpp::http::parser::request req = conn->get_request();
|
|
|
+ std::string uri = req.get_uri();
|
|
|
+ // 进入游戏大厅与进入游戏房间需要分别建立websocket长连接
|
|
|
+ if(uri == "/hall") wsopen_game_hall(conn);
|
|
|
+ else if(uri == "/room") wsopen_game_room(conn);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*wsclose_callback子函数 -- 游戏大厅websocket长连接断开后的处理函数*/
|
|
|
+ void wsclose_game_hall(wsserver_t::connection_ptr conn) {
|
|
|
+ // 获取cookie&session,如果不存在则说明websocket长连接未建立(websocket长连接建立后Session永久存在),直接返回
|
|
|
+ std::string cookie_str = conn->get_request_header("Cookie");
|
|
|
+ if(cookie_str.empty()) return;
|
|
|
+ std::string ssid_str;
|
|
|
+ if(get_cookie_val(cookie_str, "SSID", ssid_str) == false) return;
|
|
|
+ session_ptr ssp = _sm.get_session_by_ssid(std::stol(ssid_str));
|
|
|
+ if(ssp.get() == nullptr) return;
|
|
|
+ // 将玩家从游戏大厅移除
|
|
|
+ _om.exit_game_hall(ssp->get_user());
|
|
|
+ // 将玩家session设置为定时删除
|
|
|
+ _sm.set_session_expire_time(ssp->get_ssid(), SESSION_TIMEOUT);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*wsclose_callback子函数 -- 游戏房间websocket长连接断开后的处理函数*/
|
|
|
+ void wsclose_game_room(wsserver_t::connection_ptr conn) {
|
|
|
+ // 获取cookie&session,如果不存在直接返回
|
|
|
+ std::string cookie_str = conn->get_request_header("Cookie");
|
|
|
+ if(cookie_str.empty()) return;
|
|
|
+ std::string ssid_str;
|
|
|
+ if(get_cookie_val(cookie_str, "SSID", ssid_str) == false) return;
|
|
|
+ session_ptr ssp = _sm.get_session_by_ssid(std::stol(ssid_str));
|
|
|
+ if(ssp.get() == nullptr) return;
|
|
|
+ // 将玩家从在线用户管理的游戏房间中移除
|
|
|
+ _om.exit_game_room(ssp->get_user());
|
|
|
+ // 将玩家从游戏房间管理的房间中移除
|
|
|
+ _rm.remove_room_user(ssp->get_user());
|
|
|
+ // 设置玩家session为定时删除
|
|
|
+ _sm.set_session_expire_time(ssp->get_ssid(), SESSION_TIMEOUT);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*websocket长连接断开之间的处理函数*/
|
|
|
+ void wsclose_callback(websocketpp::connection_hdl hdl) {
|
|
|
+ // 获取通信连接、http请求对象和请求uri
|
|
|
+ wsserver_t::connection_ptr conn = _wssrv.get_con_from_hdl(hdl);
|
|
|
+ websocketpp::http::parser::request req = conn->get_request();
|
|
|
+ std::string uri = req.get_uri();
|
|
|
+ // 离开游戏大厅与离开游戏房间需要分别断开websocket长连接
|
|
|
+ if(uri == "/hall") wsclose_game_hall(conn);
|
|
|
+ else if(uri == "/room") wsclose_game_room(conn);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*wsmsg_callback子函数 -- 游戏大厅通信处理函数*/
|
|
|
+ void wsmsg_game_hall(wsserver_t::connection_ptr conn, wsserver_t::message_ptr msg) {
|
|
|
+ // 获取cookie&session,如果不存在则返回错误信息
|
|
|
+ std::string cookie_str = conn->get_request_header("Cookie");
|
|
|
+ if(cookie_str.empty()) {
|
|
|
+ return game_hall_resp(conn, false, "找不到Cookie信息,请重新登录");
|
|
|
+ }
|
|
|
+ std::string ssid_str;
|
|
|
+ if(get_cookie_val(cookie_str, "SSID", ssid_str) == false) {
|
|
|
+ return game_hall_resp(conn, false, "找不到Session信息,请重新登录");
|
|
|
+ }
|
|
|
+ session_ptr ssp = _sm.get_session_by_ssid(std::stol(ssid_str));
|
|
|
+ if(ssp.get() == nullptr) {
|
|
|
+ return game_hall_resp(conn, false, "Session已过期,请重新登录");
|
|
|
+ }
|
|
|
+ // 获取请求信息
|
|
|
+ std::string req_msg_body = msg->get_payload();
|
|
|
+ Json::Value req_msg;
|
|
|
+ if(json_util::deserialize(req_msg_body, req_msg) == false) {
|
|
|
+ return game_hall_resp(conn, false, "请求信息解析失败");
|
|
|
+ }
|
|
|
+ // 处理请求信息 -- 开始对战匹配与停止对战匹配
|
|
|
+ Json::Value resp = req_msg;
|
|
|
+ std::string resp_body;
|
|
|
+ // 开始对战匹配请求则将用户加入到匹配队列中,取消对战匹配请求则将用户从匹配队列中移除
|
|
|
+ if(req_msg["optype"].isNull() == false && req_msg["optype"].asString() == "match_start") {
|
|
|
+ _mm.add(ssp->get_user());
|
|
|
+ resp["result"] = true;
|
|
|
+ json_util::serialize(resp, resp_body);
|
|
|
+ conn->send(resp_body);
|
|
|
+ } else if(req_msg["optype"].isNull() == false && req_msg["optype"].asString() == "match_stop") {
|
|
|
+ _mm.remove(ssp->get_user());
|
|
|
+ resp["result"] = true;
|
|
|
+ json_util::serialize(resp, resp_body);
|
|
|
+ conn->send(resp_body);
|
|
|
+ } else {
|
|
|
+ resp["optype"] = "unknown";
|
|
|
+ resp["result"] = false;
|
|
|
+ json_util::serialize(resp, resp_body);
|
|
|
+ conn->send(resp_body);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /*wsmsg_callback子函数 -- 游戏房间通信处理函数*/
|
|
|
+ void wsmsg_game_room(wsserver_t::connection_ptr conn, wsserver_t::message_ptr msg) {
|
|
|
+ // 获取cookie&session,如果不存在则返回错误信息
|
|
|
+ std::string cookie_str = conn->get_request_header("Cookie");
|
|
|
+ if(cookie_str.empty()) {
|
|
|
+ return game_room_resp(conn, false, "找不到Cookie信息,请重新登录");
|
|
|
+ }
|
|
|
+ std::string ssid_str;
|
|
|
+ if(get_cookie_val(cookie_str, "SSID", ssid_str) == false) {
|
|
|
+ return game_room_resp(conn, false, "找不到Session信息,请重新登录");
|
|
|
+ }
|
|
|
+ session_ptr ssp = _sm.get_session_by_ssid(std::stol(ssid_str));
|
|
|
+ if(ssp.get() == nullptr) {
|
|
|
+ return game_room_resp(conn, false, "Session已过期,请重新登录");
|
|
|
+ }
|
|
|
+ // 获取房间信息
|
|
|
+ room_ptr rp = _rm.get_room_by_uid(ssp->get_user());
|
|
|
+ if(rp.get() == nullptr) {
|
|
|
+ return game_room_resp(conn, false, "找不到房间信息");
|
|
|
+ }
|
|
|
+ // 获取请求信息
|
|
|
+ std::string req_msg_body = msg->get_payload();
|
|
|
+ Json::Value req_msg;
|
|
|
+ if(json_util::deserialize(req_msg_body, req_msg) == false) {
|
|
|
+ return game_room_resp(conn, false, "请求信息解析失败");
|
|
|
+ }
|
|
|
+ // 处理请求信息 -- 下棋动作与聊天动作
|
|
|
+ rp->handler(req_msg);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*websocket长连接建立后通信的处理函数*/
|
|
|
+ void wsmsg_callback(websocketpp::connection_hdl hdl, wsserver_t::message_ptr msg) {
|
|
|
+ // 获取通信连接、http请求对象和请求uri
|
|
|
+ wsserver_t::connection_ptr conn = _wssrv.get_con_from_hdl(hdl);
|
|
|
+ websocketpp::http::parser::request req = conn->get_request();
|
|
|
+ std::string uri = req.get_uri();
|
|
|
+ // 游戏大厅通信处理与游戏房间通信处理
|
|
|
+ if(uri == "/hall") wsmsg_game_hall(conn, msg);
|
|
|
+ else if(uri == "/room") wsmsg_game_room(conn, msg);
|
|
|
+ }
|
|
|
+public:
|
|
|
+ /*成员初始化与服务器回调函数设置*/
|
|
|
+ gobang_server(const std::string &host, const std::string &user, const std::string &passwd, \
|
|
|
+ const std::string db = "gobang", uint16_t port = 4106)
|
|
|
+ : _wwwroot(WWWROOT), _ut(host, user, passwd, db, port), _sm(&_wssrv), _rm(&_ut, &_om), _mm(&_ut, &_om, &_rm) {
|
|
|
+ // 设置日志等级
|
|
|
+ _wssrv.set_access_channels(websocketpp::log::alevel::none);
|
|
|
+ // 初始化asio调度器
|
|
|
+ _wssrv.init_asio();
|
|
|
+ // 设置回调函数
|
|
|
+ _wssrv.set_http_handler(std::bind(&gobang_server::http_callback, this, std::placeholders::_1));
|
|
|
+ _wssrv.set_open_handler(std::bind(&gobang_server::wsopen_callback, this, std::placeholders::_1));
|
|
|
+ _wssrv.set_close_handler(std::bind(&gobang_server::wsclose_callback, this, std::placeholders::_1));
|
|
|
+ _wssrv.set_message_handler(std::bind(&gobang_server::wsmsg_callback, this, std::placeholders::_1, std::placeholders::_2));
|
|
|
+ }
|
|
|
+
|
|
|
+ /*启动服务器*/
|
|
|
+ void start(uint16_t port) {
|
|
|
+ // 设置监听端口
|
|
|
+ _wssrv.listen(port);
|
|
|
+ _wssrv.set_reuse_addr(true);
|
|
|
+ // 开始获取新连接
|
|
|
+ _wssrv.start_accept();
|
|
|
+ // 启动服务器
|
|
|
+ _wssrv.run();
|
|
|
+ }
|
|
|
+private:
|
|
|
+ std::string _wwwroot; // 静态资源根目录
|
|
|
+ user_table _ut; // 用户数据管理模块句柄
|
|
|
+ session_manager _sm; // 用户session信息管理模块句柄
|
|
|
+ online_manager _om; // 用户在线信息管理模块句柄
|
|
|
+ room_manager _rm; // 游戏房间管理模块句柄
|
|
|
+ matcher _mm; // 用户对战匹配管理模块句柄
|
|
|
+ wsserver_t _wssrv; // websocketpp::server 句柄
|
|
|
+};
|
|
|
+#endif
|