FENote — webSocket

Chien Wei Luo
Aug 28, 2017 · 8 min read
附上台中某創意日式料理的七貫握壽司, 但其實我也忘了這叫什麼, 不過很好吃,沒對到焦什麼的就當作藝術吧

什麼是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
  • Socket.bufferdAmount: 已被send()放入正在queue中等待傳輸但還沒發送的二進制字節數, 可以用來判斷發送是否結束
var data = new ArrayBuffer(10000)
socket.send(data)

webSocket 對象的相關事件有

  • onopen: 建立成功時觸發
  • onmessage: client端接收server端觸發
  • onerror: 錯誤時觸發
  • onclose: 連接關閉時觸發

webSocket 對象的相關方法

  • Socket.send(): 使用連接發送數據
  • Socket.close(): 關閉連接

2. 傳資料給伺服器

socket.send('some text') 
//以上是發送字串的例子

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>

ref:

[MDN]

[Websocket.org]

[WebSocket 是什么原理?为什么可以实现持久连接?]

[WebSocket 教程- 阮一峰]

)
Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade