国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

使用WebSocket方式能將群聊信息實(shí)時(shí)群發(fā)給所有在線用戶

這篇具有很好參考價(jià)值的文章主要介紹了使用WebSocket方式能將群聊信息實(shí)時(shí)群發(fā)給所有在線用戶。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一、WebSocket概述

1.1 什么是WebSocket

WebSocket是一種在單個(gè)TCP連接上進(jìn)行全雙工通信的網(wǎng)絡(luò)協(xié)議。它是為了在Web瀏覽器和Web服務(wù)器之間提供實(shí)時(shí)、雙向的通信而設(shè)計(jì)的。傳統(tǒng)的HTTP協(xié)議是一種單向通信協(xié)議,客戶端發(fā)送請(qǐng)求,服務(wù)器響應(yīng),然后連接就關(guān)閉了。而WebSocket允許在客戶端和服務(wù)器之間建立持久連接,使得雙方可以通過該連接隨時(shí)發(fā)送數(shù)據(jù)。

WebSocket協(xié)議通過在HTTP握手階段使用Upgrade頭來升級(jí)連接,使其成為全雙工通信通道。一旦升級(jí)完成,WebSocket連接就保持打開狀態(tài),允許雙方在任何時(shí)候發(fā)送數(shù)據(jù)。

WebSocket協(xié)議的特點(diǎn)包括:

  1. 全雙工通信: 客戶端和服務(wù)器之間可以同時(shí)發(fā)送和接收數(shù)據(jù),而不需要等待響應(yīng)。
  2. 低延遲: 由于連接保持打開狀態(tài),可以更快地傳輸數(shù)據(jù),適用于實(shí)時(shí)性要求較高的應(yīng)用,如在線游戲、聊天應(yīng)用等。
  3. 跨域支持: 與AJAX請(qǐng)求不同,WebSocket允許跨域通信,提供更大的靈活性。

WebSocket 端點(diǎn)通常會(huì)觸發(fā)一些生命周期事件,這些事件可以用于處理數(shù)據(jù)、管理連接的狀態(tài)等。

1.2 WebSocket的生命周期事件

  1. onOpen 事件: 在端點(diǎn)建立新WebSocket連接時(shí)并且在任何其他事件發(fā)生之前,將觸發(fā)onOpen 事件。在這個(gè)事件中,可以執(zhí)行一些初始化操作,例如記錄連接信息、添加到連接池等。
  2. onMessage 事件: 當(dāng)端點(diǎn)接收到客戶端發(fā)送的消息時(shí),將觸發(fā)onMessage 事件。在這個(gè)事件中,可以處理接收到的消息并根據(jù)需要做出相應(yīng)的反應(yīng)。
  3. onError 事件: 當(dāng)在 WebSocket 連接期間發(fā)生錯(cuò)誤時(shí),將觸發(fā)onError事件。在這個(gè)事件中可以處理錯(cuò)誤情況。
  4. onClose 事件: 當(dāng)連接關(guān)閉時(shí),將觸發(fā)onClose事件。在這個(gè)事件中可以執(zhí)行一些清理工作,例如從連接池中移除連接、記錄連接關(guān)閉信息等。

二、WebSocket實(shí)現(xiàn)群聊功能

2.1 服務(wù)端:注解式端點(diǎn)事件處理

在服務(wù)端使用@ServerEndpoint注解將 Java 類聲明成 WebSocket 服務(wù)端端點(diǎn)。

@ServerEndpoint(value = "/chat", configurator= GetHttpSessionConfigurator.class)
@Component // SpringBoot 的組件注解
public class ChatServer

對(duì)于注解式服務(wù)端端點(diǎn),WebSocket API中的生命周期事件要求使用以下方法級(jí)注解:@OnOpen @OnMessage @OnError @OnClose。

@ServerEndpoint(value = "/chat", configurator= GetHttpSessionConfigurator.class)
@Component
public class ChatServer {
    // WebSocker 生命周期函數(shù): 連接建立時(shí)調(diào)用
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) {
        // 從 EndpointConfig 中獲取之前從握手時(shí)獲取的 httpSession
        this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        String userName = (String) this.httpSession.getAttribute("username");
        // 保存已登錄用戶 session
        clients.put(userName, session);
        log.info(userName + "已與服務(wù)器建立連接");
    }

    // WebSocker 生命周期函數(shù): 收到消息時(shí)調(diào)用
    @OnMessage
    public void onMessage(String message) {
        log.info("服務(wù)器收到消息: " + message);
        // 服務(wù)器群發(fā)消息
        groupSend(message);
    }

    // WebSocker 生命周期函數(shù): 連接斷開時(shí)調(diào)用
    @OnClose
    public void onClose() {
        String userName = (String) this.httpSession.getAttribute("username");
        clients.remove(userName);
        log.info(userName + "已與服務(wù)器斷開連接");
    }
    
    ......
}

其中,服務(wù)端在收到消息時(shí),在OnMessage事件中向客戶端群發(fā)消息

// WebSocker 生命周期函數(shù): 收到消息時(shí)調(diào)用
@OnMessage
public void onMessage(String message) {
    log.info("服務(wù)器收到消息: " + message);
    // 服務(wù)器群發(fā)消息
    groupSend(message);
}
private void groupSend(String message) {
    // 遍歷所有連接,向客戶端群發(fā)消息
    message = this.httpSession.getAttribute("username") + ": " + message;
    Set<Map.Entry<String, Session>> entries = clients.entrySet();
    for (Map.Entry<String, Session> client : entries) {
        Session session = client.getValue();
        try {
            session.getBasicRemote().sendText(message); // 發(fā)送消息
        } catch (IOException e) {
        }
    }  
}

2.2 客戶端:JavaScript中的WebSocket對(duì)象

在客戶端使用JavaScript的WebSocket對(duì)象作為客戶端端點(diǎn)

// new WebSocket("ws://url")
ws = new WebSocket("ws://localhost:8848/chat");

對(duì)于JavaScript的WebSocket對(duì)象,其生命周期事件為onopen,onmessage,onerror和onclose。

ws.onmessage = function (msg) {
    let message = msg.data; // 獲取服務(wù)端發(fā)送的信息
    // 將消息顯示到頁(yè)面中
    let li = document.createElement('li');
    li.textContent = message;
    let messages = document.getElementById('messages');
    messages.appendChild(li);
    window.scrollTo(0, document.body.scrollHeight);
}

在客戶端使用WebSocket對(duì)象的send(message)方法向服務(wù)端發(fā)送消息

三、Session、Cookie實(shí)現(xiàn)24小時(shí)內(nèi)自動(dòng)識(shí)別用戶

在服務(wù)端登錄驗(yàn)證的handler中,創(chuàng)建攜帶驗(yàn)證信息的Cookie(這里圖方便直接攜帶了用戶名,實(shí)際應(yīng)該使用根據(jù)用戶UID加密過的token)并返回給客戶端瀏覽器,設(shè)定有效期為24h。

同時(shí),在會(huì)話域Session 中保存用戶名以便 WebSocket 獲?。⊿ervlet在新建Session時(shí)也會(huì)返回給客戶端帶有JSESSIONID的Cookie):

@RestController
public class UserController {
    @PostMapping("/login")
    public String login(@RequestBody UserEntity user, HttpServletRequest request, HttpServletResponse response) {
        if(loginCheck(user)) {
            Cookie cookie = new Cookie("username", user.getUserName());
            cookie.setMaxAge(24 * 60 * 60); // 設(shè)置 Cookie 的有效時(shí)間為 24h
            response.addCookie(cookie);
            // 在 session 中設(shè)置 userName 以便 WebSocket 獲取
            request.getSession().setAttribute("username", user.getUserName());
            return "success";
        } else  {
            return "failed";
        }
    }
    ......
}

此后24h內(nèi),客戶端瀏覽器訪問服務(wù)端時(shí)會(huì)攜帶以上Cookie,即使會(huì)話連接斷開,服務(wù)端也可以根據(jù)該Cookie直接驗(yàn)證用戶信息并重新在Session中保存,實(shí)現(xiàn)24h內(nèi)用戶免登錄。若會(huì)話未斷開,直接從Session中即可獲取用戶信息。

// 攔截器:登錄校驗(yàn), 不通過則跳轉(zhuǎn)到登錄界面
@Component
public class LoginProtectInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
        // 先使用 session 進(jìn)行登錄校驗(yàn)
        String username = (String) request.getSession().getAttribute("username");
        if(username != null){
            return true; // 放行
        }
        // session 校驗(yàn)失敗則用 cookie校驗(yàn)
        Cookie[] cookies = request.getCookies();
        for(Cookie cookie : cookies){
            if("username".equals(cookie.getName())){
                // 根據(jù) cookie獲取 userName
                String userName = cookie.getValue();
                // 在 session 中設(shè)置 userName
                request.getSession().setAttribute("username", userName);
                return true; // 放行
            }
        }
        // 校驗(yàn)失敗 跳轉(zhuǎn)到登錄界面
        response.sendRedirect("/login.html");
        return false;
    }
}

上面是在攔截器中進(jìn)行登陸驗(yàn)證,需要對(duì)攔截器進(jìn)行配置。

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Autowired
    private LoginProtectInterceptor loginProtectInterceptor;
    // 登錄驗(yàn)證攔截器配置
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 訪問聊天室前需要登錄驗(yàn)證
        registry.addInterceptor(loginProtectInterceptor).addPathPatterns("/chat.html");
    }
}

四、實(shí)驗(yàn)中遇到的一些問題及其解決

4.1 WebSocket獲取httpSession的方法

實(shí)驗(yàn)中需獲取Session中的用戶信息,由于WebSocket與Http協(xié)議的不同,故需要在WebSocket中故在獲取HttpSession,這里參考了以下鏈接中的方法。

https://blog.csdn.net/Zany540817349/article/details/90210075

在@ServerEndpoint注解的源代碼中,可以看到要求一個(gè)ServerEndpointConfig接口下的Configurator子類,該類中有個(gè)modifyHandshake方法,這個(gè)方法可以修改在握手時(shí)的操作,將httpSession加進(jìn)webSocket的配置中。

因此繼承這個(gè)ServerEndpointConfig.Configurator子類,重寫其modifyHandshake方法:

/** 繼承 ServerEndpointConfig.Configurator 類
 *  重寫其中的 modifyHandshake 方法
 *  在建立連接時(shí)將當(dāng)前會(huì)話的 httpSession 加入到 webSocket 的 Server端的配置中
 */
@Configuration
public class GetHttpSessionConfigurator extends ServerEndpointConfig.Configurator {
    @Override
    public void modifyHandshake(ServerEndpointConfig sec,
                                HandshakeRequest request, HandshakeResponse response) {
        HttpSession httpSession=(HttpSession) request.getHttpSession();
        sec.getUserProperties().put(HttpSession.class.getName(),httpSession);
    }
}

將繼承類加入到@ServerEndpoint注解的configurator屬性中,這樣即可在EndpointConfig中獲取HttpSession:

@Component
@ServerEndpoint(value = "/chat", configurator= GetHttpSessionConfigurator.class)
public class ChatServer {
    @OnOpen
    public void onOpen(Session session, EndpointConfig config) {
        // 從 EndpointConfig 中獲取之前從握手時(shí)獲取的 httpSession
        this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
        String userName = (String) this.httpSession.getAttribute("username");
        ......

4.2 WebSocket獲取httpSession為空(Session不一致)的問題

4.1中的獲取httpSession的方法是正確的,但是在modifyHandshake中g(shù)etHttpSession()時(shí)會(huì)報(bào)空指針異常,這里參考了以下鏈接,發(fā)現(xiàn)是服務(wù)端url寫錯(cuò)。

https://blog.csdn.net/csu_passer/article/details/78536060

在前端連接WebSocket的時(shí)候,我的代碼是這樣的:

new WebSocket("ws://127.0.0.1:8848/chat");

但是瀏覽器的地址欄是

http://localhost:8848/chat.html

鏈接中解釋說如果不使用同一個(gè)host,則會(huì)創(chuàng)建不同的連接請(qǐng)求,將WebSocket中服務(wù)端地址修改為與瀏覽器地址欄一致,則可以正確獲取到httpSession。

new WebSocket("ws://localhost:8848/chat");

實(shí)驗(yàn)源代碼

https://gitee.com/amadeuswyk/ustc-courses-net-web-socket/tree/master/

參考資料

https://blog.csdn.net/Zany540817349/article/details/90210075
https://blog.csdn.net/csu_passer/article/details/78536060文章來源地址http://www.zghlxwxcb.cn/news/detail-774095.html

到了這里,關(guān)于使用WebSocket方式能將群聊信息實(shí)時(shí)群發(fā)給所有在線用戶的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • TCP案例-實(shí)時(shí)群聊

    服務(wù)器端循環(huán)獲取所有的客戶端socket,放到一個(gè) socket的list 中,等到需要通信的時(shí)候,調(diào)用相對(duì)應(yīng)的管道就可以了 客戶端和服務(wù)器端一樣,紀(jì)要發(fā)送消息,也要接受消息 讀取線程是子線程 只能實(shí)現(xiàn)群發(fā),無法端到端 也會(huì)發(fā)給自己

    2024年04月28日
    瀏覽(18)
  • 問題:Feem無法發(fā)送信息OR無法連接(手機(jī)端無法發(fā)給電腦端)

    問題:Feem無法發(fā)送信息OR無法連接(手機(jī)端無法發(fā)給電腦端)

    目錄 前言 問題分析 資源、鏈接 其他問題 前言 需要在小米手機(jī)、華為平板、Dell電腦之間傳輸文件,試過安裝破解的華為電腦管家、小米的MIUI文件傳輸?shù)?,均無果。(小米“遠(yuǎn)程管理”ftp傳輸?shù)故强梢?,但速度太慢了,且平板打不開) 后來在B站評(píng)論中發(fā)現(xiàn)feem,可以很方便

    2024年01月20日
    瀏覽(26)
  • SpringBoot整合 websocket 實(shí)現(xiàn)群聊,點(diǎn)對(duì)點(diǎn)聊天

    SpringBoot整合 websocket 實(shí)現(xiàn)群聊,點(diǎn)對(duì)點(diǎn)聊天

    1.websocket websocket最偉大之處在于服務(wù)器和客戶端可以在給定的時(shí)間范圍內(nèi)的任意時(shí)刻,相互推送信息。瀏覽器和服務(wù)器只需要要做一個(gè)握手的動(dòng)作,在建立連接之后,服務(wù)器可以主動(dòng)傳送數(shù)據(jù)給客戶端,客戶端也可以隨時(shí)向服務(wù)器發(fā)送數(shù)據(jù)。 第一、WebSocket是HTML5中的協(xié)議,支

    2024年02月08日
    瀏覽(21)
  • python的WebSocket編程詳解,案例群聊系統(tǒng)實(shí)現(xiàn)

    1.1為什么要用websocket 如果有需求要實(shí)現(xiàn)服務(wù)端向客戶端主動(dòng)推送消息時(shí)(比如聊天室,群聊室)有哪幾種方案 輪訓(xùn):讓瀏覽器每隔兩秒發(fā)送一次請(qǐng)求,缺點(diǎn):有延時(shí),請(qǐng)求太多網(wǎng)站壓力大; 長(zhǎng)輪訓(xùn):客戶端向服務(wù)端發(fā)送請(qǐng)求,服務(wù)端最多夯20秒,一旦有新的數(shù)據(jù)就立即返回

    2024年02月02日
    瀏覽(22)
  • vue+websokect實(shí)現(xiàn)實(shí)時(shí)聊天,可單聊、可群聊(一)

    vue+websokect實(shí)現(xiàn)實(shí)時(shí)聊天,可單聊、可群聊(一)

    效果網(wǎng)站鏈接,安全性不符合實(shí)際上線使用,僅供學(xué)習(xí)交流 https://livequeen.top? 效果小程序二維碼 (需現(xiàn)在web端獲取賬號(hào)) ? ? ? ?? ? ?一個(gè)實(shí)時(shí)聊天功能 第一,肯定要能夠?qū)崿F(xiàn) 單聊或者群聊 ,所以不能無差別廣播,要實(shí)現(xiàn)向指定用戶發(fā)送廣播。 第二, 區(qū)分在線和離線

    2023年04月16日
    瀏覽(24)
  • 基于Springboot+WebSocket+Netty實(shí)現(xiàn)在線聊天、群聊系統(tǒng)

    基于Springboot+WebSocket+Netty實(shí)現(xiàn)在線聊天、群聊系統(tǒng)

    此文主要實(shí)現(xiàn)在好友添加、建群、聊天對(duì)話、群聊功能,使用Java作為后端語言進(jìn)行支持,界面友好,開發(fā)簡(jiǎn)單。 2.1、下載安裝IntelliJ IDEA(后端語言開發(fā)工具),Mysql數(shù)據(jù)庫(kù),微信Web開發(fā)者工具。 1.創(chuàng)建maven project 先創(chuàng)建一個(gè)名為SpringBootDemo的項(xiàng)目,選擇【New Project】 然后在彈出

    2024年02月14日
    瀏覽(41)
  • 了解JS三種實(shí)時(shí)通信方式——Eventsource、websocket與socket.io之間的差異和優(yōu)缺點(diǎn)

    EventSource EventSource 是一種輕量級(jí)的 API,用于獲取來自服務(wù)器的實(shí)時(shí)事件。它是 WebSockets 的替代方案,因?yàn)樗?WebSockets 更簡(jiǎn)單,更適合處理服務(wù)器向客戶端發(fā)送數(shù)據(jù)的情況。使用 EventSource ,只有服務(wù)器能夠發(fā)送消息,所以它更安全。但是,它不支持雙向通信或客戶端發(fā)送消

    2024年02月08日
    瀏覽(23)
  • 推薦一個(gè).Net Core開發(fā)的Websocket群聊、私聊的開源項(xiàng)目

    推薦一個(gè).Net Core開發(fā)的Websocket群聊、私聊的開源項(xiàng)目

    今天給大家推薦一個(gè)使用Websocket協(xié)議實(shí)現(xiàn)的、高性能即時(shí)聊天組件,可用于群聊、好友聊天、游戲直播等場(chǎng)景。 這是一個(gè)基于.Net Core開發(fā)的、簡(jiǎn)單、高性能的通訊組件,支持點(diǎn)對(duì)點(diǎn)發(fā)送、群聊、在線狀態(tài)的訂閱。 該項(xiàng)目還包含群聊例子,可以用于學(xué)習(xí)。 1、跨平臺(tái):基于.N

    2024年02月03日
    瀏覽(26)
  • 【W(wǎng)ebSocket】前端使用WebSocket實(shí)時(shí)通信

    【W(wǎng)ebSocket】前端使用WebSocket實(shí)時(shí)通信

    最近寫項(xiàng)目,需要實(shí)現(xiàn)消息通知和實(shí)時(shí)聊天的功能,就去了解了一些關(guān)于websocket的知識(shí),總結(jié)如下。 WebSocket 是一種在 Web 應(yīng)用中實(shí)現(xiàn)實(shí)時(shí)通信的協(xié)議。與傳統(tǒng)的 HTTP 請(qǐng)求不同,WebSocket 連接在客戶端和服務(wù)器之間建立一個(gè) 持久性 的 雙向通信管道 ,使得數(shù)據(jù)可以在連接打開后

    2024年02月11日
    瀏覽(23)
  • SpringBoot與webSocket實(shí)現(xiàn)在線聊天室——實(shí)現(xiàn)私聊+群聊+聊天記錄保存

    SpringBoot與webSocket實(shí)現(xiàn)在線聊天室——實(shí)現(xiàn)私聊+群聊+聊天記錄保存

    引用參考:原文章地址:https://blog.csdn.net/qq_41463655/article/details/92410518 在此基礎(chǔ)上實(shí)現(xiàn)對(duì)聊天記錄的保存。 代碼地址:鏈接:https://pan.baidu.com/s/1IJFZDa4S_DF08773sKJWeA 提取碼:jkui 思路:新建一個(gè)實(shí)體類用于保存聊天記錄,在消息發(fā)送時(shí),設(shè)置對(duì)象的各個(gè)值然后保存到數(shù)據(jù)庫(kù)中。

    2024年02月02日
    瀏覽(88)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包