天天看點

你真的了解websocket嗎

一、概述

http1.0餘http1.1支援長連接配接的詳解

HTTP作為應用層協定,其實它的生命周期在伺服器傳回結果時就已經結束了,而所謂的支援長連接配接,其實是基于’Keep-Alive’請求頭所約定,進而向下進行長連接配接發起的一種機制。該長連接配接依然是基于TCP的。

是以:

所謂HTTP1.1及以上支援長連接配接,并不是HTTP1.1可以建立長連接配接,而是它支援以請求頭的方式進行長連接配接發起(并且要求用戶端與服務端都要具備 ‘Keep-Alive: true’ )。

再說websocket之前,我們必須知道的是什麼是半雙工通信、雙工通信、全雙工通信。

1、半雙工通信

1、同一時刻資料是單向流動的,用戶端向服務端請求資料->單向,服務端向用戶端傳回資料->單向

2、伺服器不能主動的推送資料給用戶端

2、雙工通信

  • 長輪詢(長輪詢及是在請求的過程中,若是伺服器端資料并沒有更新,那麼則将這個連接配接挂起,直到伺服器推送新的資料,再傳回,然後再進入循環周期。)
長輪詢 本質上是原始輪詢技術的一種更有效的形式。向伺服器發送重複請求會浪費資源,因為必須為每個新傳入的請求建立連接配接,必須解析請求的 HTTP 頭部,必須執行對新資料的查詢,并且必須生成和傳遞響應(通常不提供新資料)。然後必須關閉連接配接并清除所有資源。長輪詢是一種伺服器選擇盡可能長的時間保持和用戶端連接配接打開的技術,僅在資料變得可用或達到逾時阙值後才提供響應,而不是在給到用戶端的新資料可用之前,讓每個用戶端多次發起重複的請求。
  • 短輪詢(短輪詢指的是在循環周期内,不斷發起請求,每一次請求都立即傳回結果,根據新舊資料對比決定是否使用這個結果。)
  • iframe流

3、全雙工通信(要知道它屬于應用層的協定,它基于TCP傳輸協定,并複用HTTP的握手通道)(在用戶端和服務端上建立了一個長久的連接配接,兩邊可以任意發資料)

二、我們好好聊聊websocket

1、寫一寫前端簡單的websocket

// 建立一個index.html檔案
// 下面直接寫WebSocket

// 隻需要new一下就可以建立一個websocket的執行個體
// 我們要去連接配接ws協定
// 這裡對應的端口就是服務端設定的端口号9999
let ws = new WebSocket('ws://localhost:9999');

// onopen是用戶端與服務端建立連接配接後觸發
ws.onopen = function() {
    ws.send('哎呦,不錯哦');
};

// onmessage是當服務端給用戶端發來消息的時候觸發
ws.onmessage = function(res) {
    console.log(res);   // 列印的是MessageEvent對象
    // 真正的消息資料是 res.data
    console.log(res.data);
};

           

2、寫一寫node 的websocket

我們在用時要安裝ws包

// 建立一個index.html檔案
// 下面直接寫WebSocket

// 隻需要new一下就可以建立一個websocket的執行個體
// 我們要去連接配接ws協定
// 這裡對應的端口就是服務端設定的端口号9999
let ws = new WebSocket('ws://localhost:9999');

// onopen是用戶端與服務端建立連接配接後觸發
ws.onopen = function() {
    ws.send('哎呦,不錯哦');
};

// onmessage是當服務端給用戶端發來消息的時候觸發
ws.onmessage = function(res) {
    console.log(res);   // 列印的是MessageEvent對象
    // 真正的消息資料是 res.data
    console.log(res.data);
};

           

3、相容性問題的解決(socket.io)

  1. socket.io的特點

易用性:封裝了服務端和用戶端,使用簡單友善

跨平台:支援跨平台,可以選擇在服務端或是用戶端開發實時應用

自适應:會根據浏覽器來自己決定是使用WebSocket、Ajax長輪詢還是Iframe流等方式去選擇最優方式,甚至支援IE5.5

  1. 安裝(npm i socket.io -S)
  2. 啟動服務,手寫服務端
// server.js檔案
const express = require('express');
const app = express();
// 設定靜态檔案夾
app.use(express.static(__dirname));
// 通過node的http子產品來建立一個server服務
const server = require('http').createServer(app);
// WebSocket是依賴HTTP協定進行握手的
const io = require('socket.io')(server);
// 監聽用戶端與服務端的連接配接
io.on('connection', function(socket) {
    // send方法來給用戶端發消息
    socket.send('青花瓷');
    // 監聽用戶端的消息是否接收成功
    socket.on('message', function(msg) {
        console.log(msg);  // 用戶端發來的消息
        socket.send('天青色等煙雨,而我在等你' );
    });
});
// 監聽3000端口
server.listen(3000);

           
  1. 前端代碼(在服務端運作後,用戶端就需要引用一個動态生成的檔案路徑,路徑是固定的直接引用即可(/socket.io/socket.io.js))
// index.html檔案
...省略
// 引用socket.io的js檔案
<script src="/socket.io/socket.io.js"></script>
<script>
    const socket = io('/');
    // 監聽與伺服器連接配接成功的事件
    socket.on('connect', () => {
        console.log('連接配接成功');
        socket.send('周傑倫');
    });
    // 監聽服務端發來的消息
    socket.on('message', msg => {
        // 這個msg就是傳過來的真消息了,不用再msg.data取值了
        console.log(`用戶端接收到的消息: ${msg}`);  
    });
    // 監聽與伺服器連接配接斷開事件
    socket.on('disconnect', () => {
        console.log('連接配接斷開成功');
    });
</script>

           

其實我自己用到的socket還是比較少,就是項目中用到了websocket,然後引申了一下,如果有時間會好好整理一下socket.io,

若有不正确的地方,請聯系我改正,謝謝!

繼續閱讀