服務器端推送技術在web開發中比較常用,在早期最簡單的解決方案是采用ajax向服務器輪詢消息,這種方式的輪詢頻率不好控制,會導致服務器的壓力。稍優的方案為:當客戶端向服務器發送請求時,服務器端會抓住這個請求不放,等有數據更新的時候才返回給客戶端,當客戶端接收到數據后再次發送請求,周而復始,這樣就大大減少了請求次數,減輕了服務器的壓力。這里我么使用webSokcet實現服務器端消息推送。
下面我們一次說一下什么是 websocket 已經如何實用js 實現對websocket 數據的獲取,并實現數據交互的長連接。
1. 什么是websocket及特點:
由于http請求只能由客戶端發起,所有當服務器資源有變化時,客戶端只能通過輪詢的方式。非常浪費資源。
websocket的特點:
服務器可以主動向客戶端推送信息,客戶端也可以主動向服務器發送信息,是真正的雙向平等對話,屬于服務器推送技術的一種建立在 TCP 協議之上,服務器端的實現比較容易可以發送文本,也可以發送二進制數據沒有同源限制,客戶端可以與任意服務器通信協議標識符是ws(如果加密,則為wss),服務器網址就是 URL。如ws:localhost:8081/msg.
2. JS示例
var ws = new WebSocket("ws://localhost:8080/msg"); ws.onopen = function(evt) { console.log("Connection open ..."); ws.send("Hello WebSockets!"); }; ws.onmessage = function(evt) { console.log("Received Message: " + evt.data); ws.close(); }; ws.onclose = function(evt) { console.log("Connection closed."); };
3. api
1. websocket構造函數
用于創建一個webSocket實例,執行后,客戶端就會與服務端連接
var ws = new WebSocket("ws://localhost:8080/msg");
2. webSocket.readyState
readyState屬性返回實例對象的當前狀態,共有四種。
CONNECTING:值為0,表示正在連接。 OPEN:值為1,表示連接成功,可以通信了。 CLOSING:值為2,表示連接正在關閉。 CLOSED:值為3,表示連接已經關閉,或者打開連接失敗 例如:if(ws.readyState ==WebSocket.CONNECTING){}
3. webSocket.onopen
用于指定連接成功后的回調函數
ws.onopen = function(evt) { console.log("Connection open ..."); ws.send("Hello WebSockets!"); };
或者:
ws.addEventListener('open', function (event) { ws.send('Hello Server!'); });
4. webSocket.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; });
5. webSocket.onmessage
用于指定收到服務器數據后的回調函數
ws.onmessage = function(event) { var data = event.data; }; ws.addEventListener("message", function(event) { var data = event.data; });
服務器數據有可能是文本,也有可能是二進制數據,需要判斷
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"); } }
除了動態判斷收到的數據類型,也可以使用binaryType屬性,顯式指定收到的二進制數據類型
// 收到的是 blob 數據
ws.binaryType = "blob";
ws.onmessage = function(e) { console.log(e.data.size); }; // 收到的是 ArrayBuffer 數據 ws.binaryType = "arraybuffer"; ws.onmessage = function(e) { console.log(e.data.byteLength); };
6. webSocket.send()
send方法用于向服務器發送數據
發送文本
ws.send("Hello WebSockets!");
發送Blob數據
var file = document .querySelector('input[type="file"]') .files[0]; ws.send(file); 發送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]; } ws.send(binary.buffer);
7. webSocket.bufferedAmount
bufferedAmount屬性,表示還有多少字節的二進制數據沒有發送出去。它可以用來判斷發送是否結束
var data = new ArrayBuffer(10000000); socket.send(data); if (socket.bufferedAmount === 0) { // 發送完畢 } else { // 發送還沒結束 }
8. webSocket.onerror
用于指定報錯時的回調函數
ws.onerror = function(event) { }; es.addEventListener("error", function(event) { });
至此,一個基于JS的WebSocket通信實例構建完畢。