WebSocket - 與伺服器通訊



Web 大部分構建在 HTTP 的請求/響應模式之上。客戶端載入網頁,然後在使用者點選下一個頁面之前沒有任何事情發生。大約在 2005 年,AJAX 開始讓 Web 感覺更加動態。但是,所有 HTTP 通訊都由客戶端控制,這需要使用者互動或定期輪詢才能從伺服器載入新資料。

能夠讓伺服器在知道新資料可用時立即將資料傳送到客戶端的技術已經存在相當一段時間了。它們被稱為“推送”“Comet”

使用長輪詢,客戶端開啟與伺服器的 HTTP 連線,並保持連線開啟直到傳送響應。每當伺服器實際擁有新資料時,它就會發送響應。長輪詢和其他技術執行良好。但是,所有這些都存在一個共同的問題,它們承載著 HTTP 的開銷,這使得它們不適合低延遲應用程式。例如,瀏覽器中的多人射擊遊戲或任何其他具有即時元件的線上遊戲。

將 Socket 帶到 Web

WebSocket 規範定義了一個 API,用於在 Web 瀏覽器和伺服器之間建立“套接字”連線。通俗地說,客戶端和伺服器之間存在一個持久連線,並且雙方都可以隨時開始傳送資料。

可以使用建構函式簡單地開啟 WebSocket 連線:

var connection = new WebSocket('ws://html5rocks.websocket.org/echo', ['soap', 'xmpp']);

ws 是 WebSocket 連線的新 URL 方案。還有wss,用於安全 WebSocket 連線,就像https 用於安全 HTTP 連線一樣。

立即將一些事件處理程式附加到連線,使您能夠知道連線何時開啟、接收傳入訊息或出現錯誤。

第二個引數接受可選的子協議。它可以是字串或字串陣列。每個字串都應表示一個子協議名稱,伺服器僅接受陣列中傳遞的子協議之一。可以透過訪問 WebSocket 物件的 protocol 屬性來確定已接受的子協議

// When the connection is open, send some data to the server
connection.onopen = function () {
   connection.send('Ping'); // Send the message 'Ping' to the server
};

// Log errors
connection.onerror = function (error) {
   console.log('WebSocket Error ' + error);
};

// Log messages from the server
connection.onmessage = function (e) {
   console.log('Server: ' + e.data);
};

與伺服器通訊

一旦我們與伺服器建立連線(當 open 事件觸發時),我們就可以開始使用連線物件上的 send(您的訊息)方法向伺服器傳送資料。它過去僅支援字串,但在最新的規範中,它現在也可以傳送二進位制訊息。要傳送二進位制資料,使用 Blob 或 ArrayBuffer 物件。

// Sending String
connection.send('your message');

// Sending canvas ImageData as ArrayBuffer
var img = canvas_context.getImageData(0, 0, 400, 320);
var binary = new Uint8Array(img.data.length);

for (var i = 0; i < img.data.length; i++) {
   binary[i] = img.data[i];
}

connection.send(binary.buffer);

// Sending file as Blob
var file = document.querySelector('input[type = "file"]').files[0];
connection.send(file);

同樣,伺服器也可能隨時向我們傳送訊息。每當發生這種情況時,onmessage 回撥就會觸發。回撥接收一個事件物件,實際訊息可以透過data屬性訪問。

WebSocket 在最新的規範中也可以接收二進位制訊息。二進位制幀可以以 Blob 或 ArrayBuffer 格式接收。要指定接收到的二進位制的格式,將 WebSocket 物件的 binaryType 屬性設定為“blob”或“arraybuffer”。預設格式為“blob”。

// Setting binaryType to accept received binary as either 'blob' or 'arraybuffer'
connection.binaryType = 'arraybuffer';
connection.onmessage = function(e) {
   console.log(e.data.byteLength); // ArrayBuffer object if binary
};

WebSocket 的另一個新增功能是擴充套件。使用擴充套件,可以傳送壓縮、多路複用等幀。

// Determining accepted extensions
console.log(connection.extensions);

跨域通訊

作為一種現代協議,跨域通訊直接整合到 WebSocket 中。WebSocket 允許任何域上的各方之間進行通訊。伺服器決定是將其服務提供給所有客戶端,還是僅提供給駐留在已定義域集中的客戶端。

代理伺服器

每種新技術都會帶來一組新問題。在 WebSocket 的情況下,它與代理伺服器的相容性,代理伺服器在大多數公司網路中充當 HTTP 連線的中介。WebSocket 協議使用 HTTP 升級系統(通常用於 HTTP/SSL)將 HTTP 連線“升級”到 WebSocket 連線。一些代理伺服器不喜歡這樣做,並且會斷開連線。因此,即使給定客戶端使用 WebSocket 協議,也可能無法建立連線。這使得下一節更加重要 :)

伺服器端

使用 WebSocket 為伺服器端應用程式建立了一種全新的使用模式。雖然 LAMP 等傳統伺服器堆疊是圍繞 HTTP 請求/響應週期設計的,但它們通常無法很好地處理大量開啟的 WebSocket 連線。同時保持大量連線開啟需要一種能夠以低效能成本接收高併發性的架構。

廣告

© . All rights reserved.