WebSocket-基礎介紹與實體物件

WebSocket 介紹

What is WebSocket?

WebSocket 是一種通訊協定(protocal),可在單個 TCP 連接上進行全雙工通訊。
在 WebSocket API 中,瀏覽器和伺服器只需要完成一次交握,兩者之間就可以建立永續性的連接,並進行雙向資料傳輸。

HTTP vs. WebSocket

最普遍常見的 protocal 是 HTTP,不過 HTTP 有個缺陷:溝通只能由客戶端(browser)發起,無法做到由服務端(server)主動向客戶端發送訊息。效率低,必須不停地發送請求確認連結。

WebSocket 與 HTTP 最大的不同是,WebSocket 是一個持續的雙向連線,不需要重新連線,不需要重新傳送 request,反應更即時。

  • HTTP 是單向請求,必須由 browser 先發出一個 request,server 端才會回傳一個 response
  • WebSocket 則是完成一次”握手”驗證之後,即可執行雙邊的訊息傳送,或是由 server 端主動回傳訊息

Why WebSocket?

當我們需要客戶端 browser 需要與 server 端保持即時、持續的雙向溝通。例:Chat apps、Real time data analytics、Social media

WebSocket 實體的方法與屬性

建立一個 WebSocket 物件

首先必須建立一個 WebSocket 物件,才能讓瀏覽器、伺服器以 WebSocket 協定進行通訊,物件一但被建立,就會自動與伺服器連線

WebSocket 的建構子,有兩個參數:

  1. url
    URL 的協議類型必須是 ws:// (非加密連線)或是 wss:// (加密連線)

  2. protocols,選擇性參數
    一個字串,或是字串組成的陣列,因此一個 Server 可以實作多個 WebSocket 子協定。

1
2
3
4
5
6
7
8
//僅傳入連線用的URL
new WebSocket('URL');

//指定伺服器使用某個sub protocol
new WebSocket('URL', 'prorocol');

//指定伺服器執行多個sub protocols
new WebSocket('URL', 'protocols[]');

下方簡單建立了一個新的 WebSocket,連到位於 http://echo.websocket.org 的伺服器。

1
var MySocket = new WebSocket('ws://echo.websocket.org');

將這段程式碼貼到瀏覽器的 console 中,執行完,查看 Network>WS,已經連上 echo.websocket.org 伺服器。

且再查看 Headers 中,可以看到狀態「101 Web Socket Protocol Handshake」

WebSOcket 的其他屬性及方法,參考這裡

查詢 WebSocket 狀態

WebSocket 物件中的 readyState 屬性是表示目前狀態,有四種值,分別代表不同的狀態。

  • WebSocket.CONNECTING:值為 0,表示正在連接中
  • WebSocket.OPEN:值為 1,表示已連結成功,可以進行通訊
  • WebSocket.CLOSING:值為 2,表示正在關閉
  • WebSocket.CLOSED:值為 3,表示為關閉狀態

可以透過狀態判斷,來做一些事,以下舉例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
switch (MySocket.readyStatus) {
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 would never happen
break;
}

WebSocket.onopen

WebSocket 物件中的onopen屬性,可以用於定義當連結成功後的回調函式,也就是當 WebSocket 完成連結時,會執行函式中的動作。

1
2
3
mySocket.onopen = function(event) {
//do something
};

若要指定多個回調函式,可以用addEventListener方法。

1
2
3
mySocket.addEventListener('open', function(event) {
//do something
});

WebSocket.onclose

WebSocket 物件中的onopen屬性,可以用於定義當關閉連結後的回調函式,也就是當 WebSocket 關閉連結時,會執行函式中的動作。

1
2
3
4
mySocket.onclose = function(event) {
//do something
//dandle close event
};

若要指定多個回調函式,可以用addEventListener方法。

1
2
3
mySocket.addEventListener('close', function(event) {
//handle close event
});

WebSocket.onmessage

WebSocket 物件中的onmessage屬性,用於定義收到 server 傳來資料後的回調函式,也就是當偵聽到 sever 傳來訊息的事件,會執行函式中的動作。

1
2
3
4
mySocket.onmessage = function(event) {
var data = event.data;
//do something for data
};

若要指定多個回調函式,可以用addEventListener方法。

1
2
3
4
mySocket.addEventListener('message', function(event) {
var data = event.data;
//do something for data
});

WebSocket.onerror

WebSocket 物件中的onerror屬性,用於定義報錯時的回調函式,也就是當偵聽到錯誤事件,會執行函式中的動作。

1
2
3
mySocket.onerror = function(event) {
//handle error event
};

若要指定多個回調函式,可以用addEventListener方法。

1
2
3
mySocket.addEventListener('error', function(event) {
//handle error event
});

傳資料給伺服器

WebSocket 的send()方法,用於向伺服器傳送訊息。

1
mySocket.send('message to server');

可以傳送的格式,包含字串、Blob、ArrayBuffer。

若要傳送複雜的資料給伺服器,可以用 JSON 格式傳送物件,以下以聊天程式應用舉例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var time = new Date();

//創建WebSocket實體
var mySocket = new WebSocket('wss://echo.websocket.org');

//當WebSocket狀態為連線時,執行的動作
mySocket.onopen = function() {
var msg = {
type: 'message',
text: document.getElementById('text').textContent,
id: 'clientID',
data: time.getTime(),
};

//先將資料轉為JSON格式,再傳資料給server
mySocket.send(JSON.stringify(msg));
};

//當瀏覽器從伺服器接收到訊息,偵聽事件被傳入onmessage並觸發函式執行
mySocket.onmessage = function() {
setTimeout(function() {
document.getElementById('text').innerHTML = '<b>Message already sent.</b>';
}, 5000);
};

參考codepen 執行結果

從伺服器接收訊息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
mySocket.onmessage = function(event) {
setTimeout(function() {
document.getElementById('text').innerHTML = '<b>Message already sent.</b>';
}, 1000);

console.log(event);
var f = document.getElementById('chatbox');
var text = '';
var msg = JSON.parse(event.data);
var time = new Date(msg.date);
var timeStr = time.toLocaleTimeString();

//僅示範switch判斷,此案例會接到的為'message'
switch (msg.type) {
case 'id':
clientID = msg.id;
setUserName();
break;
case 'message':
text =
'使用者 <em>' + msg.id + '</em> :<b>' + msg.text + '<br></b>' + '<small>登入於 ' + timeStr + '</small><br>';
break;
default:
break;
}
if (text.length) {
setTimeout(function() {
document.getElementById('chatbox').innerHTML = text;
}, 2000);
}
};

參考codepen 執行結果

關閉連線

WebSocket 的close()方法,用於結束 WebSocket 連線。

1
mySocket.close();

關閉連線後,再次查看連線狀態為 3,代表狀態為 CLOSED 關閉的狀態。

參考資料

© 2020 Leah's Blog All Rights Reserved. 本站访客数人次 本站总访问量
Theme by hiero