文章目錄
??一、技術介紹
線上演示地址: http://chat.breez.work
實時通信 (Instant Messaging,簡稱IM)是一個 實時 通信系統(tǒng),允許兩人或多人使用網(wǎng)絡實時的傳遞 文字消息 、 文件 、 語音 與 視頻交流 。[4]
場景再現(xiàn):
- ??微信聊天
- ??QQ聊天
- ??網(wǎng)站在線客服
??1.1 客戶端WebSocket
WebSocket 對象提供了用于創(chuàng)建和管理 WebSocket 連接,以及可以通過該連接 發(fā)送 和 接收數(shù)據(jù) 的 API。使用 WebSocket() 構造函數(shù)來構造一個 WebSocket。[1]
構造函數(shù)如下所示:
const webSocket = WebSocket(url[, protocols])
例子如下:
const webSocket = new WebSocket(“ws://42.193.120.86:3688/ws/小明/翠花”)
??1.1.1 函數(shù)
1、 webSocket.send()
該函數(shù)用于向服務端發(fā)送一條消息,例子如下:
webSocket.send(“Hello server!”);
2、 webSocket.close()
該函數(shù)用于關閉客戶端與服務端的連接,例子如下:
webSocket.close();
??1.1.2事件
1、webSocket.onopen
該事件用于監(jiān)聽客戶端與服務端的連接狀態(tài),如果客戶端與服務端 連接成功 則該事件觸發(fā),例子如下:
webSocket.onopen = function(event) { console.log(“連接已經(jīng)建立,可以進行通信”);};
2、webSocket.onclose
如果服務端與客戶端連接斷開,那么此事件出發(fā),例子如下:
webSocket.onclose = function(event) { console.log(“連接已經(jīng)關閉”);};
3、webSocket: message event
該事件用于監(jiān)聽服務端向客戶端發(fā)送的消息,例子如下:
webSocket.addEventListener(‘message’, function (event) { console.log(‘來自服務端的消息:’, event.data);});
4、webSocket:error event
如果客戶端與服務端發(fā)生錯誤時,那么此事件將會觸發(fā),例子如下:
webSocket.addEventListener(‘error’, function (event) { console.log(‘連接出現(xiàn)錯誤’, event);});
??1.2 服務端WebSocket
@ServerEndpoint 用于聲明一個socket服務,例子如下:
@ServerEndpoint(value = “/ws/{userId}/{targetId}”)
幾個重要的 方法 注解:
@OnOpen@OnClose@OnMessage@OnError
??二、實戰(zhàn)
??2.1、服務端
??2.1.1引入maven依賴
org.springframework.boot spring-boot-starter-websocket
??2.1.2 編寫配置類
@Configurationpublic class WebSocketConfig { @Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); }}
??2.1.3 編寫WebSocketService服務類
下面的 userId 代表 發(fā)送者 的ID號, target 代表 發(fā)送目標 ID號。
@Component@ServerEndpoint(value = “/ws/{userId}/{target}”)public class WebSocketService { //用于保存連接的用戶信息 private static ConcurrentHashMap SESSION = new ConcurrentHashMap(); //原子遞增遞減,用于統(tǒng)計在線用戶數(shù) private static AtomicInteger count = new AtomicInteger(); //消息隊列,用于保存待發(fā)送的信息 private Queue queue = new LinkedBlockingDeque(); //onOpen() //onClose() //onMessage() //onError()}
??2.1.4 建立連接
建立連接之前,判斷用戶是否已經(jīng)連接,如果沒有連接,那么將用戶session信息保存到集合,然后計數(shù)器遞增。
@OnOpen public void onOpen(Session session, @PathParam(“userId”) String userId) { if (!SESSION.containsKey(userId)) { SESSION.put(userId, session); count.incrementAndGet(); } }
??2.1.5 關閉連接
關閉連接的時候,將用戶session刪除和計數(shù)器遞減。
@OnClose public void onClose(@PathParam(“userId”) String userId) { SESSION.remove(userId); count.decrementAndGet(); }
??2.1.6 發(fā)送消息
發(fā)送采用的方法是: session.getBasicRemote().sendText(“你好”);
@OnMessage public void onMessage(String message, @PathParam(“userId”) String userId, @PathParam(“target”) String target) throws IOException { queue.add(message); Session s = SESSION.get(target); if (s == null) { Session b = SESSION.get(userId); b.getBasicRemote().sendText(“對方不在線”); } else { for (int i = 0; i < queue.size(); i++) { String msg = queue.poll(); Message m = new Message(); m.setUserId(userId); s.getBasicRemote().sendText(msg); } } }
??2.1.7 監(jiān)聽錯誤
出現(xiàn)錯誤,刪除用戶session信息和計數(shù)器遞減
@OnError public void onError(Throwable error, @PathParam(“userId”) String userId) { SESSION.remove(userId); count.decrementAndGet(); error.printStackTrace(); }
??2.2 客戶端
本案例中客戶端采用Nuxt編寫,相關代碼如下
??2.2.1 主頁面
運行截圖如圖所示:
歡迎使用喵喵號聊天 聊一下 body { background: url(‘../static/img/cat.jpg’); }
??2.2.1 聊天頁面
運行截圖如下:
小明
翠花
我的喵喵號:{{user.userId}} 對方喵喵號:{{user.targetId}} 清空消息 {{m.msg}} {{m.msg}} 系統(tǒng)消息:{{m.msg}} 發(fā)送
??三、開源地址
- ??Gitee: https://gitee.com//websocket
- 演示地址: http://chat.breez.work
??四、參考文獻
- [1]MDN: WebSocket
- [2]Nuxt: https://nuxtjs.org
- [3]Vue: https://cn.vuejs.org
- [4]百度百科: 及時通信
??收錄專欄:系統(tǒng)設計與實戰(zhàn)
原文鏈接:https://blog.csdn.net/m0_54853420/article/details/125244263?utm_source=tuicool&utm_medium=referral