WebSocket是時候展現你優秀的一面了

chenhongdong發表於2018-10-22

在工作中我們開發接觸最多的協議莫過於HTTP協議了,近些年H5的很多API和技術已經如雨後春筍般開始漸漸發揚光大了,今天我們就來一起討論下其中的一個比較有意思的API,WebSocket

首先,在介紹主角之前,總要有一個鋪墊,那麼我就來三言兩語先說一下最常見的HTTP協議吧,以示區分

三言兩語說說HTTP

HTTP是客戶端/伺服器模式中請求-響應所用的協議,在這種模式中,瀏覽器向伺服器提交HTTP請求,伺服器響應請求的資源

言下之意就是你可以把這種模式,想象成對講機,一個人,另一個人

HTTP是半雙工通訊

這種半雙工通訊的特點就是:

  • 同一時刻資料是單向流動的,客戶端向服務端請求資料->單向,服務端向客戶端返回資料->單向
  • 伺服器不能主動的推送資料給客戶端

以上就是對HTTP協議的簡單概括,那麼下面直接開始進入今天的主題

雙工通訊

在H5的websocket出現之前,為了實現這種推送技術,大家最常用的實現方式有這三種:輪詢長輪詢iframe流,但是他們三兄弟或多或少都有些美中不足

於是乎,在大神們的不斷努力下,定義了websocket這個好用的API,來完善了雙工通訊的更好實現方式

WebSocket時代已來,不要錯過!!!

WebSocket

WebSocket實現了,在客戶端和服務端上建立了一個長久的連線,兩邊可以任意發資料嗨皮

當然如果知道的更深一層的話,要知道它屬於應用層的協議,它基於TCP傳輸協議,並複用HTTP的握手通道

WebSocket是時候展現你優秀的一面了

說的再多,不如懂它,下面來看看websocket的優勢何在

WebSocket的優勢

  1. 支援雙向通訊,實時性更強(你可以來做個QQ,微信了,老鐵)
  2. 更好的二進位制支援
  3. 較少的控制開銷(連線建立後,ws客戶端、服務端進行資料交換時,協議控制的資料包頭部較少)

那麼廢話說到這裡了,接下來開始實戰,直接檢驗一下成果

一起敲敲WebSocket

我們先來寫下前端頁面的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);
};
複製程式碼

以上程式碼,除去註釋的話,也就不到10行程式碼,就把websocket的用法寫完了,so easy,使用起來很簡單啊,有木有

那麼做事要做全,我們再寫一下後臺那邊的websocket接收和傳送訊息部分吧,繼續擼

等等,在擼之前,先要安裝一下

// 後臺需要安裝ws包
npm i ws -S
複製程式碼

這裡我們用node的express來簡單搭個後臺服務,目錄結構也很簡單,如下圖

WebSocket是時候展現你優秀的一面了
下面開始擼這個server.js檔案吧

const express = require('express');
const app = express();
// 設定靜態資料夾
app.use(express.static(__dirname));
// 監聽3000埠
app.listen(3000);
// =============================================
// 開始建立一個websocket服務
const Server = require('ws').Server;
// 這裡是設定伺服器的埠號,和上面的3000埠不用一致
const ws = new Server({ port: 9999 });

// 監聽服務端和客戶端的連線情況
ws.on('connection', function(socket) {
    // 監聽客戶端發來的訊息
    socket.on('message', function(msg) {
        console.log(msg);   // 這個就是客戶端發來的訊息
        // 來而不往非禮也,服務端也可以發訊息給客戶端
        socket.send(`這裡是服務端對你說的話: ${msg}`);
    });
});
複製程式碼

這樣就搭了一個後臺服務了,訪問localhost:3000後,在控制檯就可以看到訊息了

WebSocket是時候展現你優秀的一面了
看到這裡,我們會由衷的發現,無論是前端來寫還是後臺來寫,發現其實都很類似,所以用起來比較流暢,多敲幾遍就好了,熟能生巧嘛,哈哈

接下來還沒完,由於websocket是H5標準出的東西,老版本的瀏覽器當然就不能很好的支援了,這時前端就要處理該死的相容問題了

正因如此,世上才會有了另外一個更好用的庫出現,這就是大名鼎鼎的 socket.io

下面趁此雅興,不要停,繼續來學習一下這個全雙工通訊中的王者吧

socket.io

先來看下socket.io的特別有哪些

socket.io的特點

  • 易用性:封裝了服務端和客戶端,使用簡單方便
  • 跨平臺:支援跨平臺,可以選擇在服務端或是客戶端開發實時應用
  • 自適應:會根據瀏覽器來自己決定是使用WebSocket、Ajax長輪詢還是Iframe流等方式去選擇最優方式,甚至支援IE5.5

好了,看完了特點,那就......

少點套路,多點真誠,廢話不說了,直接上手從頭擼一遍吧

socket.io安裝

// 安裝在本地專案
npm i socket.io -S
複製程式碼

啟動服務,手寫服務端

還是用node中的express框架來搭個服務,程式碼如下

// 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);
複製程式碼

辣麼,服務端的程式碼已經寫完了,接下來開始寫前端的部分,擼起袖子加油幹啊!!!

在服務端執行後,客戶端就需要引用一個動態生成的檔案路徑,路徑是固定的直接引用即可(/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>
複製程式碼

☆ 這裡要有個小提示: io建立socket的時候可以接收一個url引數

  • url可以是socket服務完整的http地址,如:io('http://localhost:3000')
  • 也可以是相對路徑,如:io('/')
  • 不填的話就表示預設連線當前路徑,如:io()

基本用法就是這些了,還有其他的劃分名稱空間、加入房間和廣播等方法沒有講到,本想繼續往下寫的

But接下來要講的,用socket.io做一個聊天室這種大招太耗費內力了,觀眾看到現在也有點疲憊了

所以識時務者為俊傑的時候到了,放在下期來放送給大家吧,辛苦各位的觀看了,886

相關文章