Websocket與伺服器通訊


Web主要圍繞HTTP的請求/響應範例構建。用戶端載入網頁,然後在使用者點選下一頁之前沒有任何操作。大約在2005年,AJAX開始讓網路感覺更有活力。仍然,所有HTTP通訊都由用戶端引導,這需要使用者互動或定期輪詢以從伺服器載入新資料。

使伺服器能夠在知道新資料可用的瞬間將資料傳送到用戶端的技術已存在很長時間了。它們的名稱如「Push」或「Comet」。

將通訊端引入Web

Websocket規範定義了在Web瀏覽器和伺服器之間建立「通訊端」連線的API。通俗地說,用戶端和伺服器之間存在持久連線,雙方都可以隨時開始傳送資料。

可以使用建構函式簡單地開啟Web通訊端連線 -

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

ws是WebSocket連線的新URL模式。對於安全的WebSocket連線,也有同樣的方式,https用於安全的HTTP連線。

通過立即將某些事件處理程式附加到連線,可以了解何時開啟連線,接收傳入訊息或發生錯誤。

第二個引數接受可選的子協定。它可以是字串或字串陣列。每個字串應代表一個子協定名稱,伺服器只接受陣列中傳遞的子協定之一。可以通過存取WebSocket物件的協定屬性來確定接受的子協定。

// 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);
};

與伺服器通訊

當連線到伺服器(當觸發開啟事件時),我們就可以使用連線物件上的send(message)方法開始向伺服器傳送資料。它過去只支援字串,但在最新的規範中,它現在也可以傳送二進位制訊息。要傳送二進位制資料,請使用BlobArrayBuffer物件。

// 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連線。保持大量連線同時開啟需要一種以低效能成本獲得高並行性的體系結構。