一.前期回顾
对于前面内容不太了解的,可以去看一看下面的文章:
二.游戏大厅长连接的建立
cpp
void wsopen_callback(websocketpp::connection_hdl hdl)
{
}
cpp
void ws_resp(wsserver_t::connection_ptr conn,Json::Value& resp)
{
std::string body;
json_util::serialize(resp,body);
conn->send(body);
}
void weopen_game_hall(wsserver_t::connection_ptr conn)
{
//游戏大厅长连接建立成功
//1.登录验证 -- 判断当前客户端是否以及成功登录
Json::Value err_resp;
std::string cookie_str = conn->get_request_header("Cookie");
if(cookie_str.empty())
{
err_resp["optype"] = "hall_ready";
err_resp["reason"] = "找不到cookie信息,请重新登录";
err_resp["result"] = false;
return ws_resp(conn,err_resp);
}
std::string ssid_str;
bool ret = get_cookie_val(cookie_str,"SSID",ssid_str);
if(ret == false)
{
err_resp["optype"] = "hall_ready";
err_resp["reason"] = "找不到ssid信息,请重新登录";
err_resp["result"] = false;
return ws_resp(conn,err_resp);
}
session_ptr ssp = _sm.get_session_by_ssid(std::stol(ssid_str));
if(ssp.get() == nullptr)
{
err_resp["optype"] = "hall_ready";
err_resp["reason"] = "找不到session信息,请重新登录";
err_resp["result"] = false;
return ws_resp(conn,err_resp);
}
//2.判定当前客户端是否重复登录
if(_om.is_in_game_hall(ssp->get_user()) || _om.is_in_game_hall(ssp->get_user()))
{
err_resp["optype"] = "hall_ready";
err_resp["reason"] = "玩家重复登录!";
err_resp["result"] = false;
return ws_resp(conn,err_resp);
}
//3.将当前客户端以及连接加入到游戏大厅
_om.enter_game_hall(ssp->get_user(),conn);
//4.给客户端响应长连接的游戏大厅连接成功
Json::Value resp_json;
resp_json["optype"] = "hall_ready";
resp_json["result"] = true;
ws_resp(conn,resp_json);
//5.记得将session设置为永久存在
_sm.set_session_expire_time(ssp->ssid(),SESSION_FOREVER);
}
void weopen_game_room(wsserver_t::connection_ptr conn)
{
}
void wsopen_callback(websocketpp::connection_hdl hdl)
{
//websocket长连接建立成功的回调函数
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")
{
//建立游戏大厅的长连接
return weopen_game_hall(conn);
}
else if(uri == "/room")
{
//建立游戏房间的长连接
return weopen_game_room(conn);
}
}
html
function get_user_info() {
$.ajax({
url: "/info",
type: "get",
success: function(res) {
var info_html = "<p>" + "用户:" + res.username + " 积分:" + res.score +
"</br>" + "比赛场次:" + res.total_count + " 获胜场次:" + res.win_count + "</p>";
var screen_div = document.getElementById("screen");
screen_div.innerHTML = info_html;
ws_hdl = new WebSocket(ws_url);
ws_hdl.onopen = ws_onopen;
ws_hdl.onclose = ws_onclose;
ws_hdl.onerror = ws_onerror;
ws_hdl.onmessage = ws_onmessage;
},
error: function(xhr) {
alert(JSON.stringify(xhr));
location.replace("/login.html");
}
})
}
function ws_onopen() {
console.log("websocket onopen");
}
function ws_onclose() {
console.log("websocket onclose");
}
function ws_onerror() {
console.log("websocket onerror");
}
目前还没有实现游戏房间内的长连接,我们先进行长连接移除的函数实现
三.游戏大厅长连接的删除
cpp
void wsclose_game_hall(wsserver_t::connection_ptr conn)
{
//游戏大厅的长连接断开
Json::Value err_resp;
std::string cookie_str = conn->get_request_header("Cookie");
if(cookie_str.empty())
{
err_resp["optype"] = "hall_ready";
err_resp["reason"] = "找不到cookie信息,请重新登录";
err_resp["result"] = false;
return ws_resp(conn,err_resp);
}
std::string ssid_str;
bool ret = get_cookie_val(cookie_str,"SSID",ssid_str);
if(ret == false)
{
err_resp["optype"] = "hall_ready";
err_resp["reason"] = "找不到ssid信息,请重新登录";
err_resp["result"] = false;
return ws_resp(conn,err_resp);
}
session_ptr ssp = _sm.get_session_by_ssid(std::stol(ssid_str));
if(ssp.get() == nullptr)
{
err_resp["optype"] = "hall_ready";
err_resp["reason"] = "找不到session信息,请重新登录";
err_resp["result"] = false;
return ws_resp(conn,err_resp);
}
//1.将玩家从游戏大厅移除
_om.exit_game_hall(ssp->get_user());
//2.将session恢复生命周期的管理
_sm.set_session_expire_time(ssp->ssid(),SESSION_TIMEOUT);
}
void wsclose_game_room(wsserver_t::connection_ptr conn)
{
//游戏房间的长连接断开
}
void wsclose_callback(websocketpp::connection_hdl hdl)
{
//1.websocket连接断开前的处理
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")
{
//游戏大厅的长连接断开
return wsclose_game_hall(conn);
}
else if(uri == "/room")
{
//游戏房间的长连接断开
return wsclose_game_room(conn);
}
}
html
window.onbeforeunload = function() {
ws_hdl.close();
}
房间内同样还是没有进行完成
四.游戏大厅内消息处理
实现按钮点击发送消息到后台服务器
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>游戏大厅</title>
<link rel="stylesheet" href="./css/common.css">
<link rel="stylesheet" href="./css/game_hall.css">
</head>
<body>
<div class="nav">网络五子棋对战游戏</div>
<!-- 整个页面的容器元素 -->
<div class="container">
<!-- 这个 div 在 container 中是处于垂直水平居中这样的位置的 -->
<div>
<!-- 展示用户信息 -->
<div id="screen"></div>
<!-- 匹配按钮 -->
<div id="match-button">开始匹配</div>
</div>
</div>
<script src="./js/jquery.min.js"></script>
<script>
var ws_url = "ws://" + location.host + "/hall";
var ws_hdl = null;
window.onbeforeunload = function() {
ws_hdl.close();
}
//按钮有两个状态:没有进行匹配的状态,正在匹配中的状态
var button_flag = "stop";
//点击按钮的事件处理:
var be = document.getElementById("match-button");
be.onclick = function() {
if (button_flag == "stop") {
//1. 没有进行匹配的状态下点击按钮,发送对战匹配请求
var req_json = {
optype: "match_start"
}
ws_hdl.send(JSON.stringify(req_json));
}else {
//2. 正在匹配中的状态下点击按钮,发送停止对战匹配请求
var req_json = {
optype: "match_stop"
}
ws_hdl.send(JSON.stringify(req_json));
}
}
function get_user_info() {
$.ajax({
url: "/info",
type: "get",
success: function(res) {
var info_html = "<p>" + "用户:" + res.username + " 积分:" + res.score +
"</br>" + "比赛场次:" + res.total_count + " 获胜场次:" + res.win_count + "</p>";
var screen_div = document.getElementById("screen");
screen_div.innerHTML = info_html;
ws_hdl = new WebSocket(ws_url);
ws_hdl.onopen = ws_onopen;
ws_hdl.onclose = ws_onclose;
ws_hdl.onerror = ws_onerror;
ws_hdl.onmessage = ws_onmessage;
},
error: function(xhr) {
alert(JSON.stringify(xhr));
location.replace("/login.html");
}
})
}
function ws_onopen() {
console.log("websocket onopen");
}
function ws_onclose() {
console.log("websocket onclose");
}
function ws_onerror() {
console.log("websocket onerror");
}
function ws_onmessage(evt) {
var rsp_json = JSON.parse(evt.data);
if (rsp_json.result == false) {
alert(evt.data);
location.replace("/login.html");
return;
}
if (rsp_json["optype"] == "hall_ready") {
alert("游戏大厅连接建立成功!");
}else if (rsp_json["optype"] == "match_success") {
//对战匹配成功
alert("对战匹配成功,进入游戏房间!");
location.replace("/game_room.html");
}else if (rsp_json["optype"] == "match_start") {
console.log("玩家已经加入匹配队列");
button_flag = "start";
be.innerHTML = "匹配中....点击按钮停止匹配!";
return;
}else if (rsp_json["optype"] == "match_stop"){
console.log("玩家已经移除匹配队列");
button_flag = "stop";
be.innerHTML = "开始匹配";
return;
}else {
alert(evt.data);
location.replace("/login.html");
return;
}
}
get_user_info();
</script>
</body>
</html>
cpp
void ws_resp(wsserver_t::connection_ptr conn,Json::Value& resp)
{
std::string body;
json_util::serialize(resp,body);
conn->send(body);
}
void wsmsg_game_hall(wsserver_t::connection_ptr conn,wsserver_t::message_ptr msg)
{
Json::Value resp_json;
std::string resp_body;
//1.获取身份
session_ptr ssp = get_session_by_cookie(conn);
if(ssp.get() == nullptr)
{
return;
}
std::string req_body = msg->get_payload();
Json::Value req_json;
bool ret = json_util::unserialize(req_body,req_json);
if(ret == false)
{
resp_json["result"] = false;
resp_json["reason"] = "请求信息解析失败";
return ws_resp(conn,resp_json);
}
//2.对于请求进行处理
if(!req_json["optype"].isNull() &&req_json["optype"].asString() == "match_start")
{
//1.开始对战匹配 : 通过匹配模块,将用户添加到匹配队列中
_mm.add(ssp->get_user());
resp_json["optype"] = "match_start";
resp_json["result"] = true;
return ws_resp(conn,resp_json);
}
else if(!req_json["optype"].isNull() &&req_json["optype"].asString() == "match_stop")
{
//2.停止对战匹配 : 通过匹配模块,将用户从匹配队列中移除
_mm.del(ssp->get_user());
resp_json["optype"] = "match_stop";
resp_json["result"] = true;
return ws_resp(conn,resp_json);
}
//3.给客户端响应
resp_json["optype"] = "unkonw";
resp_json["result"] = false;
return ws_resp(conn,resp_json);
}
void wsmsg_game_room(wsserver_t::connection_ptr conn,wsserver_t::message_ptr msg)
{
//
}
void wsmsg_callback(websocketpp::connection_hdl hdl,wsserver_t::message_ptr msg)
{
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")
{
return wsmsg_game_hall(conn,msg);
}
else if(uri == "/room")
{
return wsmsg_game_room(conn,msg);
}
}


五.目前效果演示(还没写房间内的游戏逻辑)

不要在同一个浏览器上进行登录两个用户session会有影响

两个全部匹配成功

目前房间内还没写,所以是这样的
