今天說起及時通信的時候,突然被問到時用推的方式,還是定時接受的方式,由於之前頁面都是用傳統的ajax處理,可能對ajax的定時獲取根深蒂固了,所以一時之間沒有相同怎麼會出現推的方式呢?當被提及websocket的時候突然頭腦中搭上了這根線。一、WebSocket是HTML5出的東西(協議),也就是說 ...
今天說起及時通信的時候,突然被問到時用推的方式,還是定時接受的方式,由於之前頁面都是用傳統的ajax處理,可能對ajax的定時獲取根深蒂固了,所以一時之間沒有相同怎麼會出現推的方式呢?
當被提及websocket的時候突然頭腦中搭上了這根線。
一、WebSocket是HTML5出的東西(協議),也就是說HTTP協議沒有變化,或者說沒關係,但HTTP是不支持持久連接的(長連接,迴圈連接的不算)
首先HTTP有1.1和1.0之說,也就是所謂的keep-alive,把多個HTTP請求合併為一個,但是Websocket其實是一個新協議,跟HTTP協議基本沒有關係,只是為了相容現有瀏覽器的握手規範而已,也就是說websockt和http有交集,但是並不是全部。
另外Html5是指的一系列新的API,或者說新規範,新技術。Http協議本身只有1.0和1.1,而且跟Html本身沒有直接關係。。通俗來說,你可以用HTTP協議傳輸非Html數據,就是這樣=。=是不同層次的東西。
二、websocket的特點
寫在別的特點之前,最重要的:是可以從伺服器向客戶端進行消息的推送。
(1)建立在 TCP 協議之上,伺服器端的實現比較容易。
(2)與 HTTP 協議有著良好的相容性。預設埠也是80和443,並且握手階段採用 HTTP 協議,因此握手時不容易屏蔽,能通過各種 HTTP 代理伺服器。
(3)數據格式比較輕量,性能開銷小,通信高效。
(4)可以發送文本,也可以發送二進位數據。
(5)沒有同源限制,客戶端可以與任意伺服器通信。
(6)協議標識符是ws(如果加密,則為wss),伺服器網址就是 URL。
三、websocket簡單API
1.構造函數
WebSocket 對象作為一個構造函數,用於新建 WebSocket 實例。
var ws = new WebSocket('ws://localhost:8080');
執行上面語句之後,客戶端就會與伺服器進行連接。
2.狀態返回
readyState屬性返回實例對象的當前狀態,共有四種。
CONNECTING:值為0,表示正在連接。
OPEN:值為1,表示連接成功,可以通信了。
CLOSING:值為2,表示連接正在關閉。
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;
}
3.回調函數
實例對象的onopen屬性,用於指定連接成功後的回調函數。
ws.onopen = function () {
ws.send('Hello Server!');
}
如果要指定多個回調函數,可以使用addEventListener方法。
ws.addEventListener('open', function (event) {
ws.send('Hello Server!');
});
4.關閉回調函數
實例對象的onclose屬性,用於指定連接關閉後的回調函數。
ws.onclose = function(event) {
var code = event.code;
var reason = event.reason;
var wasClean = event.wasClean;
// handle close event
};
ws.addEventListener("close", function(event) {
var code = event.code;
var reason = event.reason;
var wasClean = event.wasClean;
// handle close event
});
5.指定伺服器數據後的回調函數
實例對象的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");
}
}
除了動態判斷收到的數據類型,也可以使用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.向伺服器發送數據
實例對象的send()方法用於向伺服器發送數據。
發送文本的例子。
ws.send('your message');
發送 Blob 對象的例子。
var file = document
.querySelector('input[type="file"]')
.files[0];
ws.send(file);
發送 ArrayBuffer 對象的例子。
// 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];
}
ws.send(binary.buffer);
7.錯誤處理方式
實例對象的onerror屬性,用於指定報錯時的回調函數。
socket.onerror = function(event) {
// handle error event
};
socket.addEventListener("error", function(event) {
// handle error event
});
8.數據長度判定
實例對象的bufferedAmount屬性,表示還有多少位元組的二進位數據沒有發送出去。它可以用來判斷發送是否結束。
var data = new ArrayBuffer(10000000);
socket.send(data);
if (socket.bufferedAmount === 0) {
// 發送完畢
} else {
// 發送還沒結束
}
四、伺服器方面
有很多常用的NODE
現在只說一個特別的wobsocketd
它的最大特點,就是後臺腳本不限語言,標準輸入(stdin)就是 WebSocket 的輸入,標準輸出(stdout)就是 WebSocket 的輸出。
舉例來說,下麵是一個 Bash 腳本counter.sh。
#!/bin/bash
echo 1
sleep 1
echo 2
sleep 1
echo 3
命令行下運行這個腳本,會輸出1、2、3,每個值之間間隔1秒。
$ bash ./counter.sh
1
2
3
現在,啟動websocketd,指定這個腳本作為服務。
$ websocketd --port=8080 bash ./counter.sh
上面的命令會啟動一個 WebSocket 伺服器,埠是8080。每當客戶端連接這個伺服器,就會執行counter.sh腳本,並將它的輸出推送給客戶端。
var ws = new WebSocket('ws://localhost:8080/');
ws.onmessage = function(event) {
console.log(event.data);
};
上面是客戶端的 JavaScript 代碼,運行之後會在控制台依次輸出1、2、3。
有了它,就可以很方便地將命令行的輸出,發給瀏覽器。
$ websocketd --port=8080 ls
上面的命令會執行ls命令,從而將當前目錄的內容,發給瀏覽器。使用這種方式實時監控伺服器,簡直是輕而易舉(代碼)。
更多的用法可以參考官方示例。
Bash 腳本讀取客戶端輸入的例子
五行代碼實現一個最簡單的聊天伺服器
websocketd 的實質,就是命令行的 WebSocket 代理。只要命令行可以執行的程式,都可以通過它與瀏覽器進行 WebSocket 通信。下麵是一個 Node 實現的回聲服務greeter.js。
process.stdin.setEncoding('utf8');
process.stdin.on('readable', function() {
var chunk = process.stdin.read();
if (chunk !== null) {
process.stdout.write('data: ' + chunk);
}
});
啟動這個腳本的命令如下。
$ websocketd --port=8080 node ./greeter.js
官方倉庫還有其他各種語言的例子。
總結:
websocket的在即時通信方面的作用還是相對巨大的,畢竟解決了ajax如果反覆請求時候的大的訪問壓力,所以如果有機會應該進一步對其進行研究。