我們有沒有想過,是否有一種技術,伺服器可以主動將數據推送給客戶端進行渲染,而不再是客戶端向伺服器發出請求等待返回結果呢?接下來,讓我們一起瞭解weboskcet ...
1、背景
在開發一些前端頁面的時候,總是能接收到這樣的需求:如何保持頁面並實現自動更新數據呢?以往的常規做法,是前端使用定時輪詢後端介面,獲取響應後重新渲染前端頁面,這種做法雖然能達到類似的效果,但是依然有很多缺點,缺點就不在這裡說了,感興趣的小伙伴可以自行查閱一下。現在讓我們回憶一下,我們有沒有想過,是否有一種技術,伺服器可以主動將數據推送給客戶端進行渲染,而不再是客戶端向伺服器發出請求等待返回結果呢?接下來,讓我們一起瞭解weboskcet。
2、什麼是websocket
websocket是HTML5規範的一個部分,它借鑒了socket的思想,實現了瀏覽器與伺服器全雙工通信,達到了即時通信的效果。websocket協議基於TCP協議實現,包含初始的握手過程,以及後續的多次數據幀雙向傳輸過程,避免伺服器頻繁打開多個HTTP連接,從而能更好的節省伺服器資源和帶寬,提高工作效率與資源利用率
3、工作原理
websocket的通信規範,首先瀏覽器通過HTTP協議發出websocket的連線請求,伺服器進行響應,這個過程稱為握手,握手完成後,客戶端和伺服器之間建立一個類似TCP的連接,使用websocket協議,從而實現它們之間的通信。
4、與HTTP的關係
相同點:
1、都是基於TCP協議,且都是可靠性傳輸協議;
2、都是應用層協議;
3、websocket支持兩種資源標誌符ws(預設80埠)與wss(預設443埠),類似HTTP和HTTPS;
不同點:
1、websocket是雙向通信協議,HTTP是單向的;
2、websocket是需要瀏覽器和伺服器握手進行建立連接的,HTTP是瀏覽器發起向伺服器的連接,伺服器預先並不知道這個連接。
聯繫點:
websocket在建立握手時,數據是通過HTTP傳輸的,建立之後的數據傳輸將不再需要HTTP協議,而是websocket協議;
5、websocket創建與常用的屬性方法
5.1 websocket屬性
屬性 | 描述 |
---|---|
readyState | 只讀屬性 readyState 表示連接狀態,可以是以下值:0 :表示連接尚未建立。1 :表示連接已建立,可以進行通信。2 :表示連接正在進行關閉。3 :表示連接已經關閉或者連接不能打開。 |
bufferedAmount | 只讀屬性 bufferedAmount 已被 send() 放入正在隊列中等待傳輸,但是還沒有發出的 UTF-8 文本位元組數。 |
CONNECTING | 值為0,表示正在連接 |
OPEN | 值為1,表示連接已建立,可以進行通信 |
CLOSING | 值為2,表示連接正在關閉 |
CLOSED | 值為3,表示連接已經關閉或者連接不能打開 |
// 創建websocket
var ws = new WebSocket("ws://www.example.com");
if(ws.readyState == ws.CONNECTING){
console.log('連接正在打開');
}
ws.onopen = function () {
ws.send(consumerId);
if(ws.readyState == ws.CONNECTING){
console.log('連接正在打開1');
}
if(ws.readyState == ws.OPEN){
console.log('連接已打開');
}
console.log('已經建立連接');
// 關閉連接
// ws.close()
};
// 連接關閉時觸發
ws.onclose = function () {
if(ws.readyState == ws.CLOSED){
console.log('連接已關閉')
}
};
// 連接錯誤
ws.onerror = function () {
console.log('連接錯誤');
};
5.2 weboscket事件
事件 | 處理程式 | 描述 |
---|---|---|
open | onopen | 連接建立時觸發 |
message | onmessage | 接收消息時觸發 |
error | onerror | 發生錯誤時觸發 |
close | onclose | 關閉連接時觸發 |
5.3 客戶端的簡單示例
// 創建websocket
var ws = new WebSocket("ws://www.example.com");
// 連接成功時觸發
ws.onopen = function(e) {
console.log("Connectiong open ...");
// 發送消息
ws.send("Hello WebSocket");
};
// 接收消息時觸發
ws.onmessage = function(e) {
console.log("Received Message: " + e.data);
ws.close();
};
// 關閉連接時觸發
ws.onclose = function(e) {
console.log("Connection closed");
};
// 出現錯誤時觸發
ws.onerror = function(e) {
console.log("error");
};
5.4 服務端的簡單示例
# 創建websocket服務端
from tornado.websocket import WebSocketHandler
class wsHandler(WebSocketHandler):
# 保存連接的用戶,用於後續推送消息
connect_users = set()
# 已與客戶端建立連接
def open(self):
print("開啟WebSocket opened")
self.connect_users.add(self)
# 關閉客戶端連接
def on_close(self):
self.connect_users.remove(self)
# 接收到消息
def on_message(self, message):
self.write_message("接收到客戶端的消息:{}".format(message))
# 所有用戶發送消息
@classmethod
def send_demand_updates(cls, message):
# 使用@classmethod可以使類方法在調用的時候不用進行實例化
# 給所有用戶推送消息(此處可以根據需要,修改為給指定用戶進行推送消息)
for user in cls.connect_users:
user.write_message(message)
# 允許WebSocket的跨域請求
def check_origin(self, origin):
return True
if __name__ == "__main__":
# 調用
wsHandler。send_demand_updates("服務端發送給客戶端的消息")
註意:示例中使用python語言,需依托tornado框架搭建後端web服務端,文章中不再說明如何搭建服務端,感興趣的小伙伴可自行嘗試。tornado內置websocket模塊,能更簡單的支持使用websocket。
6、總結
websocket提供了一種低延遲、高性能的雙向數據通信,不同與web開發的請求、處理、等待響應模式,它是客戶端、服務端因為同一個連接直接就可以數據互傳的模式,特別適合實時數據交互的應用進行開發。
實用點:
1、websocket連接建立後,後續的數據傳輸都將以幀序列的形式傳輸;
2、在客戶端斷開websocket連接或服務端中斷連接前,不需要客戶端和服務端重新發起連接請求;
3、在海量併發、客戶端與伺服器交互負載流量大的情況下,節省網路帶寬資源的消耗,且客戶端發送與接收消息,都是在同一個持久連接上進行,實現了“真長連接”,真正的實現即時通信。
作者:京東物流 駱銅磊
來源:京東雲開發者社區 自猿其說Tech 轉載請註明來源