三分鐘搭建websocket實時在線聊天,項目經理也不敢這麼寫

咱們先看一下下面這張圖:前端

在這裏插入圖片描述

能夠看到這是一個簡易的聊天室,兩個窗口的消息是實時發送與接收的,這個主要就是用咱們今天要講的websocket實現的。java

websocket是什麼?

websocket是一種網絡通訊協議,咱們都知道http協議,http協議只能從客戶端主動發起,不能從服務端推送數據到客戶端,今天咱們講的websocket就是一種不只能從客戶端發送數據到服務端,也能夠主動從服務的推送數據給客戶端的一種協議。
咱們先看一張圖:web

在這裏插入圖片描述

咱們能夠看到,http請求是客戶端發起請求,服務端響應,而後斷開鏈接,客戶端發起,服務端響應的一種循環。而websocket協議是客戶端發起鏈接後,就會一直保持鏈接,期間客戶端和服務端均可以向對方發送數據,直到鏈接關閉。
websocket其餘的一些特色:ajax

(1)創建在 TCP 協議之上,服務器端的實現比較容易。

(2)與 HTTP 協議有着良好的兼容性。默認端口也是80和443,而且握手階段採用 HTTP 協議,所以握手時不容易屏蔽,能經過各類 HTTP 代理服務器。sql

(3)數據格式比較輕量,性能開銷小,通訊高效。chrome

(4)能夠發送文本,也能夠發送二進制數據。跨域

(5)沒有同源限制,客戶端能夠與任意服務器通訊。瀏覽器

(6)協議標識符是ws(若是加密,則爲wss),服務器網址就是 URL。服務器

應用場景

試想一下這樣的場景,咱們須要實現一個支付成功後,向用戶給一個成功的提示,那麼在websocket協議沒有應用以前,人們是使用一種輪詢的方式。就是客戶端定時向服務端發送請求,看有沒有收到支付金額,沒有就一直髮送,收到了再中止。相似下面的代碼:websocket

function getIsPaySuccess() {
    var timmer = setInterval(function () {
        $.ajax({
            url: '/getJayStatus',
            success: function (res) {
                if (res.status) {
                    clearInterval(timmer)
                }
            },
            fail: function () {

            }
        })
    }, 1000)
}

在發送請求的工程中,浪費了大量的資源,並且響應也不是及時的,由於我是每隔1秒請求一次,並不能馬上獲得支付成功的狀態。這時候咱們就須要用到websocket的方式了。整體來講,websocket須要用在一些能及時響應的場景中。

1. 社交訂閱
有時候咱們須要及時收到訂閱消息,好比說開獎通知,好比說在線邀請,支付結果等。

2. 多玩家遊戲
不少遊戲都是協同做戰的,玩家的操做和狀態確定須要及時同步到全部玩家。

3. 協同編輯文檔
同一份文檔,編輯狀態得同步到全部參與的用戶界面上。

4. 數據流狀態
好比說上傳下載文件,文件進度,文件是否上傳成功。

5. 多人聊天
不少場景下都須要多人蔘與討論聊天,用戶發送的消息得第一時間同步到全部用戶。

6. 股票虛擬貨幣價格
股票和虛擬貨幣的價格都是實時波動的,價格跟用戶的操做息息相關,及時推送對用戶跟盤有很大的幫助。

代碼實現

咱們用下面一段代碼來說解websocket的建立,擁有的屬性,能調用的方法和能監聽的事件:

// 鏈接狀態的枚舉
const readyStateMap = {
    0: '鏈接還沒有創建',
    1: '鏈接已創建,能夠進行通訊',
    2: '鏈接正在進行關閉',
    3: '鏈接已經關閉或者鏈接不能打開'
}
Object.freeze(readyStateMap)
class WsTest {
    constructor(url) {
        // 建立websocket實例,第一個參數是鏈接的url,沒有跨域限制,第二個參數是可接受的協議
        this.ws = new WebSocket(url);
        // readyState屬性,只讀屬性,表示鏈接狀態
        console.log(this.ws.readyState, readyStateMap[this.ws.readyState])
        // 只讀屬性 bufferedAmount 已被 send() 放入正在隊列中等待傳輸,可是尚未發出的 UTF-8 文本字節數。
        console.log(this.ws.bufferedAmount)
        this.initWs()
    }
    initWs() {
        // 事件onopen,指鏈接成功
        this.ws.onopen = () => {
            console.log(this.ws.readyState, readyStateMap[this.ws.readyState])
            // 方法,向服務端發送消息,傳輸字符串
            this.ws.send(JSON.stringify({type: 'connection'}))
        };
        // 事件onmessage,指接收到服務端消息
        this.ws.onmessage = (evt) => {
            console.log(evt.data, 'data')
            const {type, msg} = JSON.parse(evt.data);
            console.log('消息類型:' + type, '用戶id:' + msg)
            // 方法,關閉鏈接
            this.ws.close()
            console.log(this.ws.readyState, readyStateMap[this.ws.readyState])
        };
        // 事件onclose,關閉鏈接,也能夠從服務端強制斷開鏈接,這裏能夠從新發起鏈接
        this.ws.onclose = () => {
            console.log(this.ws.readyState, readyStateMap[this.ws.readyState])
        };
        // 事件onerror,通訊發生錯誤時觸發
        this.ws.onerror = () => {
            console.log(this.ws.readyState, readyStateMap[this.ws.readyState])
        };
    }
}
const ws = new WsTest('ws://203.195.156.57:30002')

上面的代碼都有註釋,應該不難看出websocket的使用方法,這段代碼能夠直接放到chrome控制檯運行:

在這裏插入圖片描述

兼容性

2.png

能夠看到幾乎全部瀏覽器都支持了。

總結

  1. websocket是一個相似http的一種通信協議。
  2. websocket最大的特色是客戶端和服務端能相互給對方發送消息。
  3. websocket普遍引用在須要實時通信的一些應用上面。
  4. websocket沒有同源限制,並且性能開銷小,通訊高效。

本文主要講了websocket協議的定義和基本用法,下一期我會結合本文開始的聊天室來實現一個具體的websocket應用。

聊天室在線體驗地址:關注公衆號:程序零世界 體驗在線聊天
學習如逆水行舟,不進則退,前端技術飛速發展,若是天天不堅持學習,就會跟不上,我會陪着你們,天天堅持推送博文,跟你們一同進步,但願你們能關注我,第一時間收到最新文章。

file

相關文章
相關標籤/搜索