FENote — webSocket

什麼是websocket? 貼上google, 萬能的維基百科如是說道:
WebSocket一種在單個TCP 連線上進行全雙工通訊的協定。 WebSocket通訊協定於2011年被IETF定為標準RFC 6455,並被RFC7936所補充規範。 WebSocketAPI也被W3C定為標準。 -Wiki
??????????
PTT 鄉民說身為前後端工程師都必須要了解 websocket
??????????
因為腦中還是滿滿的黑人問號, 所以紙上談兵的觸角就心血來潮伸向了websocket
webSocket本質上是一個基於TCP的連線技術, 協定則是'部分'基於http協定, 但要註明的是, 這裡發出的http請求與一般的http請求並不同, 而是包含了 Upgrade: websocket的Headers, 目的是為了聲明這是websocket的請求.
所以說websocket不是http協議, http只負責建立websocket連接
而client端與server端只要做一個 ‘握手’ 的動作(此時數據是通過http協議傳輸的), 其中便搭起了一道數據互相傳送的TCP橋樑(真正的數據傳輸則是不需要http協議參與)
小結: 只需要經過一次http請求, 就可以做到源源不斷的信息交互, 直到有一方關閉
而這是有淵源的, websocket的到來也是為了解決舊有的問題...
以往實現兩端交互通訊的方法:
- ajax polling : client端每隔幾秒就發送一次請求給server端
- long poll : 採取阻塞模型, client端發起連接後, 如果沒有消息就一直不返回response給客戶端, 直到有消息才返回, 之後客戶端再次建立連接
都是建立http connection 然後等候 server端處理, 反面來說, 是非常被動的
也知道這兩個方法就是非常浪費資源的, 不是需要非常快的處理速度, 就是需要超乎常理的同時接應能力
而 現在有了websocket:
彌補HTTP協議的一個缺陷, 通信只能由client端發起, websocket解決被動性, 完成協議升級後, 讓server端也會主動的推送訊息
只需要一次http請求, 你有信息再來通知我, 而不是像以往每次發出請求才得到回應, 有點像callback function的感覺(?)
建立了真正的持久連接, 解決handler處理速度過慢的問題, websocket只需要一次http握手, 整個通訊過程是建立在一次connection中, 也避免了http的無狀態性, server會一直知道client傳的信息, handler就不用反覆解析http協議, 頁不用查看身分的認證等等繁複的過程.
再小結: Websocket是一種讓瀏覽器與伺服器進行互動通訊的技術, 使用這項技術的webapp可以直接即時通訊而不需要不斷對資料更改進行輪詢(polling: 不斷請求).
簡要的說, websocket就是client端與server端之間的資料中繼(傳遞/接收)處理工具, 用以實現持久連接, 即時顯示在頁面上
使用websocket步驟:
1. 建立一個websocket對象(constructor):
var socket= new Websocket(url, [protocol])
(url指定連接的URL, protocol可選指定可接受的子協議)
webSocket 對象的屬性有
- Socket.readyState: 連接狀態,
0:尚未建立, 連接ing/ CONNECTING 1:已建立可通信/ OPEN 2:關閉ing/ CLOSING 3:已關閉or 打開連結失敗/ CLOSEDswitch (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;
}//來自阮一峰老師的範例
- Socket.bufferdAmount: 已被send()放入正在queue中等待傳輸但還沒發送的二進制字節數, 可以用來判斷發送是否結束
var data = new ArrayBuffer(10000)
socket.send(data)if(socket.bufferAmount ===0){
console.log('發送完畢')
}
else{
console.log('還沒結束')
}
webSocket 對象的相關事件有
- onopen: 建立成功時觸發
- onmessage: client端接收server端觸發
- onerror: 錯誤時觸發
- onclose: 連接關閉時觸發
webSocket 對象的相關方法
- Socket.send(): 使用連接發送數據
- Socket.close(): 關閉連接
2. 傳資料給伺服器
socket.send('some text')
//以上是發送字串的例子<input type="file"><script>
const someBlob = document.getElementById('input').files[0]
socket.send('someBlob')
</script>
//以上是發送Blob對象的例子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);//以上是發送ArrayBuffer的例子, 來自阮一峰老師的範例, 還需要研究一下
3. 從伺服器接收訊息
socket.onmessage = function(evt){...} //指定收到server數據後的回調函數4. 關閉連線
socket.close()附上官網的範例
<script language="javascript" type="text/javascript">
var wsUri = "ws://echo.websocket.org/"; //傳輸的網址, ws://.. or wss://...(安全)
var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt){ //判斷前面的wsUri是否有抓到
onOpen(evt)
};
websocket.onclose = function(evt) { //evt包含server傳過來的數據
onClose(evt)
};
websocket.onmessage = function(evt) {
onMessage(evt)
};
websocket.onerror = function(evt) {
onError(evt)
};
}
function onOpen(evt) {
writeToScreen("CONNECTED");
doSend("WebSocket rocks");
}
function onClose(evt) {
writeToScreen("DISCONNECTED");
}
function onMessage(evt) {
writeToScreen('RESPONSE: ' + evt.data+'');
websocket.close();
}
function onError(evt) {
writeToScreen('ERROR: ' + evt.data);
}
function doSend(message) {
writeToScreen("SENT: " + message);
websocket.send(message);
}
function writeToScreen(message) {
var pre = document.createElement("p"); pre.style.wordWrap = "break-word"; pre.innerHTML = message; output.appendChild(pre);
}
window.addEventListener("load", init, false);
</script>
<h2>WebSocket Test</h2>
<div id="output"></div>//reference: websocket.org
ref: