WebSocket 學習之認識websocket

一:背景介紹

近年來,隨着HTML5的誕生,WebSocket協議被提出,它實現了瀏覽器與服務器的全雙工通訊,擴展了瀏覽器與服務端的通訊功能,使服務端也能主動向客戶端發送數據。
咱們知道,傳統的HTTP協議是無狀態的,每次請求(request)都要由客戶端(如 瀏覽器)主動發起,服務端進行處理後返回response結果,而服務端很難主動向客戶端發送數據;這種客戶端是主動方,服務端是被動方的傳統Web模式 對於信息變化不頻繁的Web應用來講形成的麻煩較小,而對於涉及實時信息的Web應用卻帶來了很大的不便,如帶有即時通訊、實時數據、訂閱推送等功能的應用。在WebSocket規範提出以前,開發人員若要實現這些實時性較強的功能,常常會使用折衷的解決方法:輪詢。
輪詢是最原始的實現實時Web應用的解決方案。輪詢技術要求客戶端以設定的時間間隔週期性地向服務端發送請求,頻繁地查詢是否有新的數據改動。明顯地,這種方法會致使過多沒必要要的請求,浪費流量和服務器資源。
輪詢都是基於請求-應答模式,都不算是真正意義上的實時技術;它們的每一次請求、應答,都浪費了必定流量在相同的頭部信息上,而且開發複雜度也較大。
伴隨着HTML5推出的WebSocket,真正實現了Web的實時通訊,使B/S模式具有了C/S模式的實時通訊能力。WebSocket的工做流程是這 樣的:瀏覽器經過JavaScript向服務端發出創建WebSocket鏈接的請求,在WebSocket鏈接創建成功後,客戶端和服務端就能夠經過 TCP鏈接傳輸數據。由於WebSocket鏈接本質上是TCP鏈接,不須要每次傳輸都帶上重複的頭部數據,因此它的數據傳輸量比輪詢小 了不少。web

WebSock的特色

  1. 創建在 TCP 協議之上,服務器端的實現比較容易。瀏覽器

  2. 與 HTTP 協議有着良好的兼容性。默認端口也是80和443,而且握手階段採用 HTTP 協議,所以握手時不容易屏蔽,能經過各類 HTTP 代理服務器。服務器

  3. 數據格式比較輕量,性能開銷小,通訊高效。app

  4. 能夠發送文本,也能夠發送二進制數據。socket

  5. 沒有同源限制,客戶端能夠與任意服務器通訊。ide

  6. 協議標識符是ws(若是加密,則爲wss),服務器網址就是 URL。函數

WebSocket 對象做爲一個構造函數,用於新建 WebSocket 實例,執行完以後,客戶端就會與服務端進行鏈接
下面看一個簡單的例子:性能

var ws = new WebSocket('http://127.0.0.1:8003');ws.onopen = function (evt) {
    console.log('鏈接已打開!');
    ws.send('Hello WebSocket!!!');}ws.onmessage = function (message) {
    console.log('接收到信息:' + message.data);
    ws.close();}ws.onclose = function (evt) {
  consoel.log('鏈接已關閉!')}

二:WebSock 客戶端API

1. 新建 WebSocket 實例

var ws = new WebSocket('http://127.0.0.1:8003');

執行上面語句以後,客戶端就會與服務器進行鏈接。this

2. webSocket.onopen

實例對象的onopen屬性,用於指定鏈接成功後的回調函數。加密

ws.onopen = function () {
  ws.send('Hello Server!');}

若是要指定多個回調函數,可使用addEventListener方法。

ws.addEventListener('open', function (event) {
  ws.send('Hello Server!');});
3. webSocket.onmessage

實例對象的onmessage屬性,用於指定收到服務器數據後的回調函數。

ws.onmessage = function(event) {
  var data = event.data;
  // 處理數據};ws.addEventListener("message", function(event) {
  var data = event.data;
  // 處理數據});

注意,服務器數據多是文本,也多是二進制數據(blob對象或Arraybuffer對象)。所以你還須要動態判斷數據類型

ws.onmessage = function(event){
  if(typeof event.data === String) {
    console.log("Received data string");
  }

  if(event.data instanceof ArrayBuffer){
    var buffer = event.data;
    console.log("Received arraybuffer");
  }}
4. webSocket.send()

實例對象的send()方法用於向服務器發送數據。

//       發送文本的例子ws.send('your message');

//      發送 Blob 對象的例子var file = document  .querySelector('input[type="file"]')
  .files[0];ws.send(file);
5. webSocket.onerror

實例對象的onerror屬性,用於指定報錯時的回調函數。

socket.onerror = function(event) {
  // 這裏寫報錯事件   };socket.addEventListener("error", function(event) {
  // 這裏寫監聽的報錯事件});
6. webSocket.onclose

實例對象的onclose屬性,用於指定鏈接關閉後的回調函數。

ws.onclose = function(event) {
  var code = event.code;
  var reason = event.reason;
  var wasClean = event.wasClean;
  // 這裏寫關閉事件};ws.addEventListener("close", function(event) {
  var code = event.code;
  var reason = event.reason;
  var wasClean = event.wasClean;
  //這裏寫監聽的關閉事件});
7. webSocket.readyState

readyState屬性返回實例對象的當前狀態,共有四種:

  1. CONNECTING:值爲0,表示正在鏈接

  2. OPEN:值爲1,表示鏈接成功,能夠通訊了

  3. CLOSING:值爲2,表示鏈接正在關閉

  4. CLOSED:值爲3,表示鏈接已經關閉,或者打開鏈接失敗

switch (ws.readyState) {
  case WebSocket.CONNECTING:
    // do something
    break;
  case WebSocket.OPEN:
    // do something
    break;
  case WebSocket.CLOSING:
    // do something
    break;
  case WebSocket.CLOSED:
    // do something
    break;
  default:
    // this never happens
    break;}
  1. webSocket.bufferedAmount
    實例對象的bufferedAmount屬性,表示還有多少字節的二進制數據沒有發送出去。它能夠用來判斷髮送是否結束

var data = new ArrayBuffer(10000000);socket.send(data);if (socket.bufferedAmount === 0) {
  // 發送完畢} else {
  // 發送還沒結束}
  1. webSocket.onerror
    實例對象的onerror屬性,用於指定報錯時的回調函數

socket.onerror = function(event) {
  // handle error event};socket.addEventListener("error", function(event) {
  // handle error event});
相關文章
相關標籤/搜索