網頁版五子棋項目的問題處理

文章目錄

  • config.WebSocketConfig
  • 將鍵值對加?OnlineUserManager中
  • 線程安全、鎖
  • ObjectMapper來處理json
  • 針對多開情況的判定
  • 處理連接關閉、異常(玩家中途退出)后的不合理操作
  • 游戲大廳數據更新

config.WebSocketConfig

把MatchAPI注冊進去

? 在addHandler 之后,再加上?個.addInterceptors(newHttpSessionHandshakeInterceptor()) 代碼,這樣可以把之前登錄過程中往HttpSession中存放的數據(主要是User對象),到WebSocket的session中.?便后?的代碼中獲取到當前用戶信息

// 通過 .addInterceptors(new HttpSessionHandshakeInterceptor() 這個操作來把 HttpSession ?的屬性放到 WebSocket 的 session 中 // 參考: https://docs.spring.io/springframework/docs/5.0.7.RELEASE/spring-framework-reference/web.html#websocketserver-handshake// 然后就可以在 WebSocket 代碼中 WebSocketSession ?拿到 HttpSession 中的 attribute.registry.addHandler(matchAPI, "/findMatch").addInterceptors(new HttpSessionHandshakeInterceptor());}

將鍵值對加?OnlineUserManager中

? 當玩家斷開websocket連接,則將鍵值對從OnlineUserManager中刪除
? 在玩家連接好的過程中,隨時可以通過userId來查詢到對應的會話,以便向客戶端返回數據
由于存在兩個??,游戲?廳和游戲房間,使?兩個哈希表來分別存儲兩部分的會話
在這里插入圖片描述

線程安全、鎖

由于handlerMatch 在單獨的線程中調?.因此要考慮到訪問隊列的線程安全問題.需要加上鎖
? 每個隊列分別使?隊列對象本?作為鎖即可.
? 在??處使?wait來等待,直到隊列中達到2個元素及其以上,才喚醒線程消費隊列

private void handlerMatch(Queue<User> matchQueue) {synchronized (matchQueue){try {// 很可能隊列初始情況為0,用while循環檢查,不能用if(匹配成功需要有兩個玩家)while (matchQueue.size() < 2){matchQueue.wait();return;}//從隊列中取出兩個玩家User player1 = matchQueue.poll();User player2 = matchQueue.poll();System.out.println("匹配出了兩個玩家:"+player1.getUsername()+" , "+player2.getUsername());//獲取玩家的websocket的會話,告訴玩家 排到了WebSocketSession session1 = onlineUserManager.getFromGameHall(player1.getUserId());WebSocketSession session2 = onlineUserManager.getFromGameHall(player2.getUserId());//理論上來說,匹配隊列中的玩家一定是在線狀態(前面已經處理過,斷開連接的玩家會被移除匹配隊列//為了謹慎,再進行一次判斷if (session1 == null){//玩家1不在線就把玩家2放回到匹配隊列中matchQueue.offer(player2);return;}if (session2 == null){//玩家2不在線就把玩家1放回到匹配隊列中matchQueue.offer(player1);return;}//TODO 把這兩個玩家放到一個游戲房間中Room room = new Room();roomManager.add(room,player1.getUserId(),player2.getUserId());//給玩家反饋信息 匹配到了MatchResponse response1 = new MatchResponse();response1.setOk(true);response1.setMessage("matchSuccess");session1.sendMessage(new TextMessage(objectMapper.writeValueAsString(response1)));MatchResponse response2 = new MatchResponse();response2.setOk(true);response2.setMessage("matchSuccess");session2.sendMessage(new TextMessage(objectMapper.writeValueAsString(response2)));}catch (IOException | InterruptedException e){e.printStackTrace();}
public void add(User user){if (user.getScore() < 2000){synchronized (normalQueue){normalQueue.offer(user);normalQueue.notify();}System.out.println("把玩家"+user.getUsername()+"加入到了 normalQueue 中!");} else if (user.getScore() >= 2000 && user.getScore() < 3000) {synchronized (highQueue){highQueue.offer(user);highQueue.notify();}System.out.println("把玩家"+user.getUsername()+"加入到了 highQueue 中!");}else {synchronized (veryHighQueue){veryHighQueue.offer(user);veryHighQueue.notify();}System.out.println("把玩家"+user.getUsername()+"加入到了 veryHighQueue 中!");}}
public void remove(User user){if (user.getScore() < 2000){synchronized (normalQueue){normalQueue.remove(user);}System.out.println("把玩家"+user.getUsername()+"移除normalQueue隊列");} else if (user.getScore() >= 2000 && user.getScore() < 3000) {synchronized (highQueue){highQueue.remove(user);}System.out.println("把玩家"+user.getUsername()+"移除highQueue隊列");}else {synchronized (veryHighQueue){veryHighQueue.remove(user);}System.out.println("把玩家"+user.getUsername()+"移除veryHighQueue隊列");}}

ObjectMapper來處理json

MatchResponse response = new MatchResponse();response.setOk(false);response.setReason("您尚未登錄! 不能進行匹配!");session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));//TextMessage--一個文本格式的websocket數據 通過ObjectMapper把對象轉成JSON字符串!

針對多開情況的判定

//  獲取玩家身份信息(哪個玩家在游戲大廳中 建立了連接)//   (注意!!!可能出現玩家身份信息為空的現象----玩家直接通過 /game_hall.html 進入游戲大廳try {User user = (User) session.getAttributes().get("user");//判斷當前用戶是否已經登錄,禁止多開WebSocketSession webSocketSession = onlineUserManager.getFromGameHall(user.getUserId());if( webSocketSession != null || onlineUserManager.getFromGameRoom(user.getUserId()) != null){MatchResponse response = new MatchResponse();response.setOk(true);response.setReason("此用戶已登錄! 禁止重復登錄!");response.setMessage("repeatConnection");session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));//session.close();//連接斷開return;}
//判斷用戶有沒有多開if (onlineUserManager.getFromGameHall(user.getUserId()) != null|| onlineUserManager.getFromGameRoom(user.getUserId()) !=null){response.setOk(false);response.setReason("禁止多開游戲");session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));return;}
success: function(data) { // bodyconsole.log(JSON.stringify(data));if (data && data.userId > 0) {// 登錄成功, 跳轉到游戲?廳alert("登錄成功!")location.assign('/game_hall.html');} else {alert("登錄失敗! 用戶名密碼錯誤! 或者 該賬號正在游戲中!");}}

下線的時候注意針對多開情況的判定,避免錯誤刪除玩家

try {//玩家下線,移除User user = (User) session.getAttributes().get("user");//  把該玩家設置為下線狀態// 避免移除多開情況時,錯誤刪除WebSocketSession webSocketSession = onlineUserManager.getFromGameHall(user.getUserId());if (webSocketSession == session){onlineUserManager.exitGameHall(user.getUserId());}matcher.remove(user);//玩家正在匹配中,連接斷開,移除玩家}

處理連接關閉、異常(玩家中途退出)后的不合理操作

此時連接已經關閉,不應該再發送信息給客戶端

catch (NullPointerException e){e.printStackTrace();//連接已經關閉,不應該再發送信息給客戶端
//            //把 當前用戶未登錄 這個信息返回回去
//            MatchResponse response = new MatchResponse();
//            response.setOk(false);
//            response.setReason("您尚未登錄! 不能進行匹配!");
//            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
//            //TextMessage--一個文本格式的websocket數據 通過ObjectMapper把對象轉成JSON字符串!}

用戶操作不可控,謹慎處理可能發生的情況

WebSocketSession existSession = onlineUserManager.getFromGameRoom(user.getUserId());if (existSession != session){System.out.println("當前的會話不是玩家游戲中的會話, 不做處理!");return;}

游戲大廳數據更新

對局結束后,分數、對局數會發生改變,因此游戲大廳中的數據需要從數據庫中獲取

public Object getUserInfo(HttpServletRequest req){try {HttpSession httpSession = req.getSession(false);User user = (User) httpSession.getAttribute("user");//去數據庫中找最新的數據(一輪比賽后數據會有變化User newUser = userMapper.selectByName(user.getUsername());return newUser;}catch (NullPointerException e){return new User();}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/74026.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/74026.shtml
英文地址,請注明出處:http://en.pswp.cn/web/74026.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【初探數據結構】歸并排序與計數排序的序曲

&#x1f4ac; 歡迎討論&#xff1a;在閱讀過程中有任何疑問&#xff0c;歡迎在評論區留言&#xff0c;我們一起交流學習&#xff01; &#x1f44d; 點贊、收藏與分享&#xff1a;如果你覺得這篇文章對你有幫助&#xff0c;記得點贊、收藏&#xff0c;并分享給更多對數據結構感…

算法刷題記錄——LeetCode篇(8.7) [第761~770題](持續更新)

更新時間&#xff1a;2025-03-30 算法題解目錄匯總&#xff1a;算法刷題記錄——題解目錄匯總技術博客總目錄&#xff1a;計算機技術系列博客——目錄頁 優先整理熱門100及面試150&#xff0c;不定期持續更新&#xff0c;歡迎關注&#xff01; 763. 劃分字母區間 給你一個字…

Pod 網絡與 CNI 的作用

在 Kubernetes 中&#xff0c;Pod 網絡 是實現容器間通信的核心機制&#xff0c;每個 Pod 擁有獨立的 IP 地址&#xff0c;可直接跨節點通信。CNI&#xff08;Container Network Interface&#xff09; 是 Kubernetes 的網絡插件標準&#xff0c;負責為 Pod 分配 IP、配置網絡規…

使用keepalived結合tomcat和nginx搭建三主熱備架構

角色主機名軟件IP地址用戶client172.25.250.90keepalivedVIP172.25.250.100keepalivedVIP172.25.250.101keepalivedVIP172.25.250.102masterserverAkeepalived, nginx172.25.250.30backupserverBkeepalived, nginx172.25.250.31backupserverCkeepalived, nginx172.25.250.32web…

STRUCTBERT:將語言結構融入預訓練以提升深度語言理解

【摘要】最近&#xff0c;預訓練語言模型BERT&#xff08;及其經過穩健優化的版本RoBERTa&#xff09;在自然語言理解&#xff08;NLU&#xff09;領域引起了廣泛關注&#xff0c;并在情感分類、自然語言推理、語義文本相似度和問答等各種NLU任務中達到了最先進的準確率。受到E…

leetcode_977. 有序數組的平方_java

977. 有序數組的平方https://leetcode.cn/problems/squares-of-a-sorted-array/ 1.題目 給你一個按 非遞減順序 排序的整數數組 nums&#xff0c;返回 每個數字的平方 組成的新數組&#xff0c;要求也按 非遞減順序 排序。 示例 1&#xff1a; 輸入&#xff1a;nums [-4,-1…

Nginx—nginx.conf 配置結構詳解

一、nginx.conf 配置結構 函數 說明 main 全局配置 event 配置工作模式以及連接數 http http模塊相關配置 server 虛擬主機配置&#xff0c;可以有多個 location 路由規則&#xff0c;表達式 upstream 集群、內網服務器&#xff08;負載均衡也在這里邊配&#xff…

斐波那契數列----C語言

關于斐波那契 已知&#xff1a; 問題背景&#xff1a;一對兔子從第3個月開始每月生一對新兔子&#xff0c;新兔子同樣在第3個月開始繁殖。 關鍵觀察&#xff1a; 第1個月&#xff1a;1對&#xff08;初始兔子&#xff09;。 第2個月&#xff1a;1對&#xff08;未成熟&#…

vulhub靶場—— Tomcat8

目錄 一、漏洞描述 二、靶場搭建 三、漏洞復現 1、弱密碼 2、文件上傳 一、漏洞描述 環境描述&#xff1a; Tomcat 支持后臺部署 war 文件&#xff0c;可以直接將 webshell 部署到 web 目錄下。tomcat 默認的管理頁面 manager 使用 basic 認證用戶名和密碼登錄&#xff0…

使用 Spring AI Aliabab Module RAG 構建 Web Search 應用

使用 Spring AI Alibaba 構建大模型聯網搜索應用 Spring AI 實現了模塊化 RAG 架構&#xff0c;架構的靈感來自于論文“模塊化 RAG&#xff1a;將 RAG 系統轉變為類似樂高的可重構框架”中詳述的模塊化概念。 Spring AI 模塊化 RAG 體系 總體上分為以下幾個步驟&#xff1a; …

一些練習 C 語言的小游戲

一些練習 C 語言的小游戲 — 1. 猜數字游戲 描述&#xff1a;程序隨機生成一個數字&#xff0c;玩家需要猜測這個數字&#xff0c;并根據提示&#xff08;太高或太低&#xff09;調整猜測&#xff0c;直到猜中為止。 功能點&#xff1a; 隨機數生成 (rand() 函數)。循環和…

關于中文編程的一些思考

隨著信息化與數字化的發展&#xff0c;工業4.0時代亦將徐徐到來。當計算機的普及程度越來越高&#xff0c;數據的產生、傳輸、處理等變得越來越快、越來越大量的時候&#xff0c;人們想要自動化辦公的愿望也越來越強烈&#xff0c;希望能將自身從耗費腦力但是重復繁瑣的工作中解…

golang 日志log與logrus

目錄 一、Go 標準庫 log 詳解 1. 功能特點 2. 常用函數 3. 示例代碼 4. 優勢和局限 二、第三方庫 logrus 詳解 1. 功能特點 2. 核心功能 3. 示例代碼 4. 優勢和擴展性 三、總結 1. 何時選擇 log&#xff1f; 2. 何時選擇 logrus&#xff1f; 3. 對比總結 一、Go 標…

消費品行業創新創業中品類創新與數字化工具的融合:以開源 AI 智能客服、AI 智能名片及 S2B2C 商城小程序為例

摘要&#xff1a; 本文聚焦于消費品行業的創新與創業&#xff0c;深入探討“選擇大于努力”這一觀點&#xff0c;強調品類選擇在品牌發展中的關鍵作用。同時&#xff0c;詳細分析了品類創新對于新消費品牌崛起以及傳統品牌轉型的重要意義。在此基礎上&#xff0c;引入開源 AI 智…

Razer macOS v0.4.10快速安裝

鏈接點這里下載最新的 .dmg 文件。將下載的 .dmg 映像文件拖入 應用程序 文件夾中。若首次打開時出現安全警告【什么扔到廢紙簍】&#xff0c;這時候點擊 Mac 的“系統偏好設置”-> “安全性與隱私”-> “通用”&#xff0c;然后點擊底部的 “打開”。【或者仍然打開】 對…

Flask項目部署:Flask + uWSGI + Nginx

目錄 1,網絡架構 2,環境安裝 2.1,安裝yum:Shell軟件包管理器 2.2 安裝python 2.3 安裝uWSGI 2.4 安裝Flask 3,上傳工程包到服務器,打包Flask項目 4,創建和配置 uwsgi 配置文件 uwsgi.ini 4.1配置文件 4.2配置文件注釋詳解 5,啟動服務 6,安裝nginx 7,nginx配置 8,…

[FPGA基礎學習]實現流水燈與按鍵暫停

FPGA實現LED流水燈 1.vscode的安裝和使用 vscode下載 Visual Studio Code - Code Editing. Redefined vscode插件&#xff08;Verilog-HDL/SystemVerilog&#xff09;下載 quartus綁定vscode 2.用6個LED完成周期為1秒的跑馬燈效果 流水燈模塊設計 時鐘輸入 DE2-115開發板…

【TensorRT】TensorRT從安裝到推理——Python 環境下 MobileNetV4 三分類任務

我想開發一個基于深度學習的分類小軟件&#xff0c;逐漸了解到了TensorRT在模型推理速度上的優勢&#xff0c;經過一下午資料的查找實現了將onnx模型轉為TensorRT格式模型的推理及測試過程。將實現過程記錄下來方便日后查看。 本文實驗設備是MX350顯卡 2G顯存 一 、安裝Tenso…

1.兩數之和(Java)

1. 題目描述 LeetCode 1. 兩數之和&#xff08;Two Sum&#xff09; 給定一個整數數組 nums 和一個目標值 target&#xff0c;請你在該數組中找出和為目標值的那兩個整數&#xff0c;并返回它們的索引。 示例 1&#xff1a; 輸入&#xff1a;nums [2,7,11,15], target 9 …

《深入探索 Python 數據分析:用 Pandas 高效處理與可視化大型數據集》

《深入探索 Python 數據分析:用 Pandas 高效處理與可視化大型數據集》 引言:從零到分析高手 數據是當代社會最寶貴的資源,而數據分析技能是現代職業人不可或缺的一部分。在數據科學的領域中,Python 已成為當之無愧的“首選語言”,其強大的生態系統和簡潔的語法讓人如虎添…