第一次看到
ws://和wss://時候,感覺好高級啊,還有這種協議,
Websocket 歷史
WebSocket是在2008年6月誕生的1,經由IEFT標準化后,2009年chrome 4第一個提供了該標準支持,并默認啟用,于2011年由IEFT標準化為RFC 6455,
現在的瀏覽器均已支持該標準,
Websocket 出現的背景
思考一下我們經常遇到的一種需求場景,要求在某個網頁下,網頁的內容可以實時更新,
這種情況下,最大眾化的方式就是輪詢介面了,即通過定時器,定時請求介面,獲取到最新的資訊后,將內容更新到頁面中,如下:
setInterval(() => {
queryAPI().then(() => update());
}, 1000);
但是我們知道,這種定時器的延時并不是很精確,而且加上介面的請求時延,實際時間可能不止代碼中所預先設定的時間長度,所以這種實時更新是偽實時更新,
除此之外,還有一點可能會經常遇到,即,我們更新資訊并總是要更新整個頁面上所有可以看到的資訊,我們更關注一些經常變化的資訊,比如狀態,狀態的資訊可能大小只有幾個位元組,但是我們輪詢介面拿到的資訊卻是這個頁面的所有資訊,大小自然不只幾個位元組,但是除狀態以外的資訊都可以視作是冗余的,

我們實際只需要一個欄位,而且即使后端提供只回傳狀態的介面,但實際在一個請求中還要計算ip報文頭的大小,依舊是很占用帶寬的,
輪詢這種解決方案目前依舊是非常流行,最新的輪詢技術是Comet,這種技術雖然可以實作雙向通信,但仍然需要反復發出請求,而且在Comet中普遍采用的HTTP長連接也會消耗服務器資源2,
Websocket通信模式
了解網路的都知道,資料傳輸分為單工、半雙工、全雙工三種作業模式,
Websocket是基于TCP的,使用全雙工通信模式的協議,他使得客戶端和服務端之間的資料交換變得更簡單,而且,作為一個作業在全雙工模式下的協議,服務端可以在建立連接后隨時向客戶端推送訊息,
由于協議是基于TCP的,所以websocket也是需要建連和關閉連接的,但要注意的是,一般在websocket的握手通常指的是:客戶端發送一個http請求到服務端,服務端回應后標志這個鏈接建立起來,而不是指tcp的三次握手,
另外在RFC 6455 1.1節「Background」中介紹:WebSocket通過HTTP埠的80和443進行作業,并支持HTTP代理和中介,
原文:it is designed to work over HTTP ports 80 and 443 as well as to support HTTP proxies and intermediaries
為了實作和HTTP的兼容性,WebSocket握手使用HTTP的Upgrade頭將HTTP協議轉換成Websocket協議,
作為一種協議,websocket自然也是有其用于協議控制的頭部資訊的,但是相對于HTTP請求每次都要帶上完整的頭部資訊,傳輸資料時,websocket資料包的頭部資訊就相對較小,從而降低了控制開銷,
相對于前文所提到的輪詢介面,websocket可以做到服務端直接向客戶端傳輸資料,省去了客戶端發起請求的步驟,同時沒有間隔時間,只要服務端內容變化,就可以告知客戶端,實時性上有了很大的提高,
Websocket 使用
WebSocket使用十分簡單,只需要關注以下API:
WebSocket(url[, protocol])建構式
使用 new WebSocket(xxx) 創建物件時,會同時建立與服務器的連接

WebSocket.onopen,WebSocket.onclose
分別對應連接成功、失敗時的回呼,這里可以做一些初始化、銷毀的作業
WebSocket.onmessage
實際處理資料是用的該函式
在資料處理完成后,需要移除回呼函式,不然可能會影響到其他地方的處理
const ws = new WebSocket('ws://sdf.com');
function handleData(evt) {
// handle server data.
}
ws.onmessage = handleData;
ws.addEventListener('message', handleData);
WebSocket.send
主動向服務端發送訊息,可以通過send和onmessage進行資料互動,如:
ws.send('list');
?
ws.onmessage = evt => {
const data = https://www.cnblogs.com/keepsmart/archive/2022/03/15/evt.data;
if (data ==='hello') {
console.log('world');
return ;
}
try {
const obj = JSON.parse(data);
switch (obj.type) {
case 'list':
// do something.
}
} catch (ex) {}
}
WebSocket.close
關閉連接
Node服務端的實作,這個就參考相關的庫吧,比較復雜,
衍生知識
http協議至今,主要經歷了三個版本,
-
http1.0 短連接,單工通信
- http/1.0默認的模型是短連接,每個HTTP請求都由他自己獨立完成,下圖左1,可以看到每一個http請求都對應了一個建立連接關閉連接的階段,每一個請求都有TCP握手和揮手的階段,
- 在這個模型下,想要做到實時更新頁面資料,只能考慮輪詢,
-
http1.1 支持長鏈接,半雙工通信
- 1.0之后的版本,1.1會讓某個連接保持一定的時間,在這段時間里重復發送一系列請求(下圖左2),就是保活,
- http2.0 支持多路復用,全雙工通信

參考文獻
[1] [whatwg] TCPConnection feedback
[2] wiki
[3] RFC 6455
[4] Websocket教程
[5] HTTP1.x連接管理
本文首發于個人博客,歡迎來撩啊^-^,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/444423.html
標籤:其他

