91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Vue中前后端怎么使用WebSocket

發布時間:2023-05-11 15:51:01 來源:億速云 閱讀:141 作者:iii 欄目:開發技術

這篇文章主要介紹“Vue中前后端怎么使用WebSocket”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“Vue中前后端怎么使用WebSocket”文章能幫助大家解決問題。

什么是websocket

WebSocket 是一種網絡通信協議。RFC6455定義了它的通信標準。

WebSocket是HTML5下一種新的協議(websocket協議本質上是一個基于tcp的協議)

它實現了瀏覽器與服務器全雙工通信,能更好的節省服務器資源和帶寬并達到實時通訊的目的

http是一種無狀態,無連接,單向的應用層協議,它采用了請求/響應模型,通信請求只能由客戶端發起,服務端對請求做出應答處理。這樣的弊端顯然是很大的,只要服務端狀態連續變化,客戶端就必須實時響應,都是通過javascript與ajax進行輪詢,這樣顯然是非常麻煩的,同時輪詢的效率低,非常的浪費資源(http一直打開,一直重復的連接)。

于是就有了websocket,Websocket是一個持久化的協議,它是一種全面雙工通訊的網絡技術,任意一方都可以建立連接將數據推向另一方,websocket只需要建立一次連接,就可以一直保持

websocket 原理

websocket約定了一個通信的規范,通過一個握手的機制,客戶端和服務器之間能建立一個類似tcp的連接,從而方便它們之間的通信

在websocket出現之前,web交互一般是基于http協議的短連接或者長連接

websocket是一種全新的協議,不屬于http無狀態協議,協議名為"ws"

說它是TCP傳輸,主要體現在建立長連接后,瀏覽器是可以給服務器發送數據,服務器也可以給瀏覽器發送請求的。當然它的數據格式并不是自己定義的,是在要傳輸的數據外層有ws協議規定的外層包的。

websocket與http的關系

相同點:

都是基于tcp的,都是可靠性傳輸協議,都是應用層協議

不同點:

WebSocket是雙向通信協議,模擬Socket協議,可以雙向發送或接受信息

HTTP是單向的

WebSocket是需要瀏覽器和服務器握手進行建立連接的

而http是瀏覽器發起向服務器的連接,服務器預先并不知道這個連接

聯系

WebSocket在建立握手時,數據是通過HTTP傳輸的。但是建立之后,在真正傳輸時候是不需要HTTP協議的

關系圖

Vue中前后端怎么使用WebSocket

Vue中前后端怎么使用WebSocket

實際開發

我們有一個需求就是報警數據來了之后在前端報警處理,不使用websocket就只能通過輪詢每3秒調用一次接口,在吧查回來的數據進行判斷,如果多了就開始調接口繼續操作,這樣很浪費資源。

使用websocket之后,建立連接之后。后端察覺數據變化之后,通過他的send方法通知前端,前端通過onmessage提示調用,可以在里面直接調用查詢數據接口繼續操作。

我們這里是建立連接通過他數據變化后端通知前端,前端有個方法會執行,我們在這個方法里面調用我們查詢接口,也可以是后端把這條數據發回來我們處理,根據實際情況而定。

后端代碼

我們后端是做了容器化的分布式的,主要代碼如下

public class WebSocketConfig {
    /**
     * 如果使用Springboot默認內置的tomcat容器,則必須注入ServerEndpoint的bean;
     * 如果使用外置的web容器,則不需要提供ServerEndpointExporter,下面的注入可以注解掉
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}
 
 
public class WebSocketServer {

    //與某個客戶端的連接會話,需要通過它來給客戶端發送數據
    private Session session;

    private static CopyOnWriteArraySet<WebSocketServer> webSockets = new CopyOnWriteArraySet<>();
    //用來存放每個客戶端對應的WebSocket對象。
    private static Map<String,Session> sessionPool = new HashMap<>();

    /**
     * 連接成功后調用的方法
     * @param session
     * @param key
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("key") String key) throws IOException {
        //key為前端傳給后端的token
        this.session = session;
        //從token中獲取到userid當做區分websocket客戶端的key
        Long userId = JwtHelper.getUserId(key);
        sessionPool.put(String.valueOf(userId),session);
        if (sessionPool.get(String.valueOf(userId))==null){
            webSockets.add(this);
        }
        webSockets.add(this);
        System.out.println("webSocket連接成功");
        System.out.println("WebSocket有新的連接,連接總數為:"+webSockets.size());
    }

    /**
     * 連接關閉調用的方法
     */
    @OnClose
    public void onClose() {
        webSockets.remove(this);
        System.out.println("webSocket連接關閉");
    }

    /**
     * 收到客戶端消息后調用的方法,根據業務要求進行處理,這里就簡單地將收到的消息直接群發推送出去
     * @param message 客戶端發送過來的消息
     */
    @OnMessage
    public void onMessage(String message) {
        //心跳檢測
        int beginIndex = 10;
        if ("HeartBeat".equals(message.substring(0,9))){
            String token = message.substring(beginIndex);
            System.out.println("token1"+token);
            if (!"".equals(token)){
                System.out.println("token2"+token);
                Long userId = JwtHelper.getUserId(token);
                sendTextMessage(String.valueOf(userId),"ok");
            }
        }
        System.out.println("WebSocket收到客戶端消息:"+message);
    }
    /**
     * 發生錯誤時的回調函數
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("發生錯誤");
        error.printStackTrace();
    }

    /**
     * 實現服務器主動推送消息
     */
    //單點消息發送
    public void sendTextMessage(String key,String message){
        Session session = sessionPool.get(key);
        if (session!=null){
            try {
                session.getBasicRemote().sendText(message);
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

}

前端代碼

1.在src/utils 建立websocket.js 引入文件,這個websocket是全局的,通過登錄,和退出控制,在哪兒頁面都可以使用。

// 提示信息
import { Message } from 'element-ui'
// 引入token 解析用戶id在后端處理
import { getToken } from '@/utils/auth'

var url = 'ws://后端地址/equipment/websocket/'

var ws
var tt
var lockReconnect = false //避免重復連接
var clientId = getToken() //cookies中獲取token值

var websocket = {
// 建立連接
  Init: function (clientId) {
    if ('WebSocket' in window) {
      ws = new WebSocket(url + clientId)
    } else if ('MozWebSocket' in window) {
      ws = new MozWebSocket(url + clientId)
    } else {
      // console.log('您的瀏覽器不支持 WebSocket!')
      return
    }
    // websocket 生命周期根據websocket狀態自己會執行
    // websocket 成功 失敗 錯誤 斷開 這里會自動執行
    // 這個方法后端通過send調用 這個方法會執行和接收參數
    ws.onmessage = function (e) {
      // console.log('接收消息:' + e.data)
      heartCheck.start()
      if (e.data == 'ok') {
        //心跳消息不做處理
        return
      }
      Message({
        message: e.data,
        type: 'success'
      })
      //messageHandle(e.data)
    }
    ws.onclose = function () {
      console.log('連接已關閉')
      Message({
        message: '報警功能連接已關閉',
        type: 'error'
      })
      reconnect(clientId)
    }
    ws.onopen = function () {
      // console.log('連接成功')
      Message({
        message: '報警功能連接成功',
        type: 'success'
      })
      heartCheck.start()
    }

    ws.onerror = function (e) {
      // console.log('數據傳輸發生錯誤')
      Message({
        message: '數據傳輸發生錯誤',
        type: 'error'
      })
      reconnect(clientId)
    }
  },
  // 我們單獨寫了一個方法 調用ws的關閉方法,這樣就可以在退出登錄的時候主動關閉連接
  //關閉連接
  onClose: function () {
    console.log('主動關閉連接!')
    //關閉websocket連接和關閉斷開重連機制
    lockReconnect = true
    // 調用 上面的websocket關閉方法
    ws.close()
  },
  // 前端的send給后端發信息
  Send: function (sender, reception, body, flag) {
    let data = {
      sender: sender,
      reception: reception,
      body: body,
      flag: flag
    }
    let msg = JSON.stringify(data)
    // console.log('發送消息:' + msg)
    ws.send(msg)
  },
  // 返回ws對象
  getWebSocket () {
    return ws
  },
  // websocket 自帶的狀態碼意思提示
  getStatus () {
    if (ws.readyState == 0) {
      return '未連接'
    } else if (ws.readyState == 1) {
      return '已連接'
    } else if (ws.readyState == 2) {
      return '連接正在關閉'
    } else if (ws.readyState == 3) {
      return '連接已關閉'
    }
  }
}

// 刷新頁面后需要重連 
if (window.performance.navigation.type == 1 && getToken() != null) {
  //刷新后重連
  // reconnect(clientId);
  websocket.Init(clientId)
  //如果websocket沒連接成功,則開始延遲連接
  if (ws == null) {
    reconnect(clientId)
  }
}

export default websocket

//根據消息標識做不同的處理
function messageHandle (message) {
  let msg = JSON.parse(message)
  switch (msg.flag) {
    case 'command':
      // console.log('指令消息類型')
      break
    case 'inform':
      // console.log('通知')
      break
    default:
    // console.log('未知消息類型')
  }
}
// 重連方法 刷新頁面 連接錯誤 連接關閉時調用
function reconnect (sname) {
  if (lockReconnect) {
    return
  }
  lockReconnect = true
  //沒連接上會一直重連,設置延遲避免請求過多
  tt && clearTimeout(tt)
  tt = setTimeout(function () {
    // console.log('執行斷線重連...')
    websocket.Init(sname)
    lockReconnect = false
  }, 4000)
}

//心跳檢測 跟后端是對應的 會進行處理
// 連接成功 和后端推消息時調用
var heartCheck = {
  timeout: 1000 * 60 * 3,
  timeoutObj: null,
  serverTimeoutObj: null,
  start: function () {
    // console.log('開始心跳檢測')
    var self = this
    this.timeoutObj && clearTimeout(this.timeoutObj)
    this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj)
    this.timeoutObj = setTimeout(function () {
      //這里發送一個心跳,后端收到后,返回一個心跳消息,
      //onmessage拿到返回的心跳就說明連接正常
      // console.log('心跳檢測...')
      ws.send('HeartBeat:' + clientId)
      self.serverTimeoutObj = setTimeout(function () {
        if (ws.readyState != 1) {
          ws.close()
        }
        // createWebSocket();
      }, self.timeout)
    }, this.timeout)
  }
}

2.在登錄和退出的時候進行websocket進行建立連接和關閉連接,就是在vuex(src/store/modules/user.js)調用這里方法(詳細的Vuex做登錄主頁文章會有)。

// 引入外部文件
import websocket from '@/utils/websocket'
// 請求
const actions = {
  // 登錄
  async login (ctx, data) {
    // 調用mutations里的方法存到state
    // 登錄成功后創建websocket連接
    // res.data 是token
    websocket.Init(res.data)
    ctx.commit('SET_TOKEN', res.data)
  },
 
  // 退出登錄
  logout (ctx) {
   // 主動關閉連接
    websocket.onClose()
    Message.success('退出成功,請重新登錄')
  }
}

3.在需要用到websocket使用,我們這里是在首頁使用。

// 引入websocket文件
import websocket from '@/utils/websocket'

// 登錄成功一進到頁面的時候調用
created() {
   this.getWebSocket()
 },

// getWebSocket()方法
method: {
   // websocket 接受消息
    getWebSocket() {
      // websocket.getWebSocket()這個是websocket里面方法返回ws對象(websocket.js)
      let ws = websocket.getWebSocket()
      // 通過ws這個對象獲取這個websocket里面后端推消息前端執行的方法onmessage。
      // 給他賦給我們自己方法 this.websocketonmessage
     websocketonmessage(e)就會執行
      ws.onmessage = this.websocketonmessage
    },
    //接收到消息的回調函數
    websocketonmessage(e) {
      // e后端傳回來參數
      // console.log(e.data);
      // 防止心跳監測,返回來的ok 對方法執行的影響(心跳監測方法也會執行一次)
      if (e.data == 'ok') {
        //心跳消息不做處理
        return
      }
      // 需要監測的接口 我們查詢數據的接口 在進行處理
        this.alarmerlist()
    },
}

細節:這樣登錄創建連接之后,后端察覺到數據變化,就通過他的send方法給我們推消息我們前端websocket.js文件的onmessage這個方法會自己調用執行并會接受參數。我們在需要的頁面引入websocket使用。把它賦值我們自己寫的方法,這樣數據一變化我們就會調用一次查詢接口,進行處理,大大節約性能(http要用輪詢一直調用查詢接口)。

關于“Vue中前后端怎么使用WebSocket”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

鹤岗市| 海原县| 垣曲县| 达尔| 图片| 玉溪市| 紫金县| 上高县| 泉州市| 新营市| 吴旗县| 黄冈市| 应用必备| 从江县| 舞阳县| 蚌埠市| 静宁县| 淮安市| 民乐县| 清水河县| 亚东县| 吴江市| 平远县| 外汇| 赣榆县| 阳江市| 监利县| 施秉县| 枣强县| 三都| 佛冈县| 乐业县| 松阳县| 鞍山市| 泗洪县| 行唐县| 永昌县| 贺兰县| 枝江市| 清苑县| 长沙市|