這一章介紹如何用WebSocket API來控制協議和建立應用,運用http://websocket.org 提供的現有WebSocket服務器,咱們能夠收發消息、建立一些簡單的WebSocket應用。一步一步的學習使用WebSocket API,最後咱們會討論瀏覽器的支持度和連通性。這一章的重點是WebSocket 協議在Web客戶端的應用,在稍後的章節會介紹WebSocket協議以及其使用環境。javascript
綜述:java
入門:web
// Create new WebSocket connection var ws = new WebSocket("ws://www.websocket.org"); //測試了下連接不上。
// Connecting to the server with one protocol called myProtocol var ws = new WebSocket("ws://echo.websocket.org", "myProtocol"); //myProtocol 是假設的一個定義好的且符合標準的協議。
你能夠傳遞一個協議的數組。編程
var echoSocket = new WebSocket("ws://echo.websocket.org", ["com.kaazing.echo","example.imaginary.protocol"]) //服務端會選擇其中一個使用 echoSocket.onopen = function(e) { // Check the protocol chosen by the server console.log(echoSocket.protocol); }
輸出:com.kaazing.echo數組
// Event handler for the WebSocket connection opening ws.onopen = function(e) { console.log("Connection open..."); };
open事件觸發的時候,意味着協議握手結束,WebSocket已經準備好收發數據。若是你的應用收到open事件,就能夠肯定服務端已經處理了創建鏈接的請求,且贊成和你的應用通訊。瀏覽器
// 接受文本消息的事件處理實例: ws.onmessage = function(e) { if(typeof e.data === "string"){ console.log("String message received", e, e.data); } else { console.log("Other message received", e, e.data); } };
除了文本消息,WebSocket消息機制還能處理二進制數據,有Blob和ArrayBuffer兩種類型,在讀取到數據以前須要決定好數據的類型。緩存
// 設置二進制數據類型爲blob(默認類型) ws.binaryType = "blob"; // Event handler for receiving Blob messages ws.onmessage = function(e) { if(e.data instanceof Blob){ console.log("Blob message received", e.data); var blob = new Blob(e.data); } };
//ArrayBuffer ws.binaryType = "arraybuffer"; ws.onmessage = function(e) { if(e.data instanceof ArrayBuffer){ console.log("ArrayBuffer Message Received", + e.data); // e.data即ArrayBuffer類型 var a = new Uint8Array(e.data); } };
//異常處理 ws.onerror = function(e) { console.log("WebSocket Error: " , e); //Custom function for handling errors handleErrors(e); };
固然你能夠調用close方法斷開與服務端的連接來觸發onclose事件,安全
ws.onclose = function(e) { console.log("Connection closed", e); };
鏈接失敗和成功的關閉握手都會觸發關閉事件,WebSocket的對象的readyState屬性就表明鏈接的狀態(2表明正在關閉,3表明已經關閉)。關閉事件有三個屬性能夠用來作異常處理和重獲: wasClean,code和reason。wasClean是一個bool值,表明鏈接是否乾淨的關閉。 若是是響應服務端的close事件,這個值爲true,若是是別的緣由,好比由於是底層TCP鏈接關閉,wasClean爲false。code和reason表明關閉鏈接時服務端發送的狀態,這兩個屬性和給入close方法的code和reason參數是對應的,稍後會描述細節。服務器
WebSocket 對象有兩個方法:send()和close()websocket
一旦在服務端和客戶端創建了全雙工的雙向鏈接,可使用send方法去發送消息,
//發送一個文本消息 ws.send("Hello WebSocket!");
當鏈接是open的時候send()方法傳送數據,當鏈接關閉或獲取不到的時候回拋出異常。一個一般的錯誤是人們喜歡在鏈接open以前發送消息。以下所示:
// 這將不會工做 var ws = new WebSocket("ws://echo.websocket.org") ws.send("Initial data");
正確的姿式以下,應該等待open事件觸發後再發送消息。
var ws = new WebSocket("ws://echo.websocket.org") ws.onopen = function(e) { ws.send("Initial data"); }
若是想經過響應別的事件去發送消息,能夠檢查readyState屬性的值爲open的時候來實現。
function myEventHandler(data) { if (ws.readyState === WebSocket.OPEN) { //open的時候便可發送 ws.send(data); } else { // Do something else in this case. //Possibly ignore the data or enqueue it. } }
發送二進制數據:
// Send a Blob var blob = new Blob("blob contents"); ws.send(blob); // Send an ArrayBuffer var a = new Uint8Array([8,6,7,5,3,0,9]); ws.send(a.buffer);
Blob對象和JavaScript File API一塊兒使用的時候至關有用,能夠發送或接受文件,大部分的多媒體文件,圖像,視頻和音頻文件。這一章末尾會結合File API提供讀取文件內容來發送WebSocket消息的實例代碼。
使用close方法來關閉鏈接,若是鏈接以及關閉,這方法將什麼也不作。調用close方法只後,將不能發送數據。
ws.close();
close方法能夠傳入兩個可選的參數,code(numerical)和reason(string),以告訴服務端爲何終止鏈接。第三章講到關閉握手的時候再詳細討論這兩個參數。
// 成功結束會話 ws.close(1000, "Closing normally"); //1000是狀態碼,表明正常結束。
WebSocket對象有三個屬性,readyState,bufferedAmount和Protocol。
WebSocket對象經過只讀屬性readyState來傳達鏈接狀態,它會更加鏈接狀態自動改變。下表展現了readyState屬性的四個不一樣的值。
屬性
|
值
|
狀態
|
WebSocket.CONNECTING
|
0 |
鏈接正在進行,但尚未創建
|
WebSocket.OPEN
|
1
|
鏈接已經創建,能夠發送消息。 |
WebSocket.CLOSING
|
2
|
鏈接正在進行關閉握手 |
WebSocket.CLOSED
|
3
|
鏈接已經關閉或不能打開 |
瞭解當前鏈接的狀態有助於咱們調試。
// 10k var THRESHOLD = 10240; //創建鏈接 var ws = new WebSocket("ws://echo.websocket.org"); // Listen for the opening event ws.onopen = function () { setInterval( function() { //緩存未滿的時候發送 if (ws.bufferedAmount < THRESHOLD) { ws.send(getApplicationState()); } }, 1000); }; //使用bufferedAmount屬性發送數據能夠避免網絡飽和。
在構造函數中,protocol參數讓服務端知道客戶端使用的WebSocket協議。而WebSocket對象的這個屬性就是指的最終服務端肯定下來的協議名稱,當服務端沒有選擇客戶端提供的協議或者在鏈接握手結束以前,這個屬性都是空的。
完整實例
<h2>Websocket Echo Client</h2> <div id="output"></div>
// 初始化鏈接和事件 function setup() { output = document.getElementById("output"); ws = new WebSocket("ws://echo.websocket.org/echo"); // 監聽open ws.onopen = function (e) { log("Connected"); sendMessage("Hello WebSocket!"); } // 監聽close ws.onclose = function (e) { log("Disconnected: " + e.reason); } //監聽errors ws.onerror = function (e) { log("Error "); } // 監聽 messages ws.onmessage = function (e) { log("Message received: " + e.data); //收到消息後關閉 ws.close(); } } // 發送消息 function sendMessage(msg) { ws.send(msg); log("Message sent"); } // logging function log(s) { var p = document.createElement("p"); p.style.wordWrap = "break-word"; p.textContent = s; output.appendChild(p); // Also log information on the javascript console console.log(s); } // Start setup();
判斷瀏覽器是否支持:
if (window.WebSocket){ console.log("This browser supports WebSocket!"); } else { console.log("This browser does not support WebSocket."); }