WebSocket 介紹
WebSocket 是網路協定的一種,只需要連線一次。Client 與 Server 便能保持連線進行雙向傳輸溝通,不必一直發送 Request 保持溝通。
請求網址通常是:
ws://example.com
//SSL 加密後
wss://example.com
以下開始建立 WebSocket 連線測試,分別建立 Server 跟 Client 端。
Server 端
建立連接環境
使用 node.js 來寫後端程式。安裝好 node.js 後,建立專案資料夾後執行:
npm init
然後下載兩個套件來使用:
// Web 框架
npm install express --save
// 處理 WebSocket 協定
npm install ws --save
新增一個 server.js 檔,內容如下:
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
| //import express 和 ws 套件 const express = require('express') const SocketServer = require('ws').Server
//指定開啟的 port const PORT = process.env.PORT || 3000
//建立 express 的物件,並監聽 3000 port ,開啟後在 console 中提示 const server = express() .listen(PORT, () => console.log(`Listening on ${PORT}`))
//將 express 交給 SocketServer 開啟 WebSocket 的服務 const wss = new SocketServer({ server })
//當 WebSocket 從外部連結時執行 wss.on('connection', ws => {
//連結時執行此 console 提示 console.log('Client connected')
//當 WebSocket 的連線關閉時執行 ws.on('close', () => { console.log('Close connected') }) })
|
執行 server.js 檔。測試檔案是否 ok。cmd 環境專案資料夾下輸入:
node server.js
若成功開啟,console 會出現提示 Listening on 3000
ps. 注意 package.json 裡的 “main”: “server.js”,
接收發送訊息(接收 Clinet 訊息處理後回傳)
開啟 WebSocket 後, Server 端使用 send 發送訊息,接收則是如同在 connection 內監聽 close 一樣,只是加入對 message 設定監聽,並接收一個參數 data(Client 端發送的訊息):
1 2 3 4 5 6 7 8 9 10 11 12 13
| wss.on('connection', ws => { console.log('Client connected')
//對 message 設定監聽,接收從 Client 發送的訊息 ws.on('message', data => { //data 為 Client 發送的訊息,現在將訊息原封不動發送出去 ws.send(data) })
ws.on('close', () => { console.log('Close connected') }) })
|
Server 端直接發送資料給 Clinet 端(用 setInterval )
// setInterval() 則是固定延遲了某段時間之後,才去執行對應的程式碼,然後 “不斷循環”。
發送訊息改寫:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| wss.on('connection', ws => { console.log('Client connected')
//固定送最新時間給 Client const sendNowTime = setInterval(()=>{ ws.send(String(new Date())) },1000)
ws.on('message', data => { ws.send(data) })
ws.on('close', () => { //連線中斷時停止 setInterval clearInterval(sendNowTime) console.log('Close connected') }) })
|
多人連線環境( ws 套件使用 clients )
當某個 Client 發送訊息時,同時讓 Server 告知所有其他連接中的 Client,Server 所收到的訊息,也同時接收到 Server 回傳的資料。類似廣播功能。
改寫監聽 message 部分, 加入 Clients 發送的訊息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| wss.on('connection', ws => { console.log('Client connected')
ws.on('message', data => { //取得所有連接中的 client let clients = wss.clients
//做迴圈,發送訊息至每個 client clients.forEach(client => { client.send(data) //傳送時間 //client.send(new Date().toTimeString()); }) })
ws.on('close', () => { console.log('Close connected') }) })
|
Client 端
建立連接環境
新增一個專案資料夾,新增 index.js,內容如下:
1 2 3 4 5 6 7 8 9 10 11 12
| //使用 WebSocket 網址連結 Server let ws = new WebSocket('ws://localhost:3000')
//開啟後執行的動作,指定一個 function 會在連結 WebSocket 後執行 ws.onopen = () => { console.log('open connection') }
//關閉後執行的動作,指定一個 function 會在連結中斷後執行 ws.onclose = () => { console.log('close connection') }
|
接著新增 index.html,內容如下:
1 2 3 4 5 6
| // 引用 index.js <html> <body> <script src='./index.js'></script> </body> </html>
|
接收發送訊息( Client 發送訊息給 Server 處理後得到回傳資料)
Client 端用 onmessage 處理接收,用 send 送出訊息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| let ws = new WebSocket('ws://localhost:3000')
ws.onopen = () => { console.log('open connection') }
ws.onclose = () => { console.log('close connection') }
//接收 Server 發送的訊息,Server 回傳的資料會在 event 的 data 屬性 ws.onmessage = event => { console.log(event) }
|
測試
連結是否成功
server 端訊息(cmd 環境下)
用瀏覽器開啟 index.html,連結 server 端。打開 console,會顯示 open connection 字樣,輸入 ws 看訊息。
列出 WebSocket 的物件有哪些屬性, Client 是用 onmessage 屬性接收由 Server 發送的資料。
server 端接收訊息後,是否回傳
雙向連線環境建立完後,開啟瀏覽器 index.html 。然後在 console 環境中,輸入 ws.send('hello')
,來測試。Server 是否有接收到資料(console 環境內看)。
將 WebSocket 部署至 Heroku
利用 Git 的方式上傳至 Heroku
Heroku 註冊並開啟新 app
註冊網址
註冊後登入,從右上 New 選單中, Create new app 建立。
安裝 Heroku CLI
Heroku CLI
到上面網站,依照本身電腦系統下載後安裝。
建立 Git 環境
切換到要上傳的專案資料夾下,輸入以下指令:
// 初始化資料夾
git init
// 打包檔案
git add .
// 寫註解
git commit -m "upload"
// 登入 Heroku,開啟登入頁面,輸入帳密
heroku login
// 設定連結的 heroku 遠端主機
heroku git:remote -a (Heroku 上 的 App 名稱)
e.g.
heroku git:remote -a xxx
// 上傳至 heroku
git push heroku master
上傳前程式調整(上述的範例)
package.json
1 2 3 4 5
| "scripts": { "test": "echo \"Error: no test specified\" && exit 1", // 加上此行,node 後面要對應 main 屬性的值 "start": "node server.js" },
|
server.js
頁面加上 WebSocket test!! 字樣
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
| 加上
//引用'http'模組 const http = require('http');
// 建立一個server並指定他的頁面資訊,並監聽 port ,開啟後在 console 中提示 const server = http.createServer((req, res) => { // 進入網站首頁顯示 index if (req.url == '/') { // 設定 response header res.writeHead(200, { 'Context-Type': 'text/html' }); // 回應內容 res.write('<h1>WebSocket test!!</h1>'); // 送出 response res.end(); // 不是的話顯示 404 例如 /abc/ } else { res.writeHead(200, { 'Context-Type': 'text/html' }); res.write('<h1>404</h1>'); res.end(); } }).listen(PORT, () => console.log(`Listening on ${PORT}`))
// 註解以下程式
// 建立 express 的物件,並監聽 port ,開啟後在 console 中提示 // const server = express().listen(PORT, () => console.log(`Listening on ${PORT}`))
|
index.js
將原本連結的網址調整成 Heroku 給的網站
let ws = new WebSocket('ws://appname.herokuapp.com/')
然後在瀏覽器開啟 index.html,打開 console。看是否有 open connection 字樣,確認是否成功。
ps:
因為 WebSocket 只連線一次就可以雙向傳輸,因此開發人員工具的 Network 看不到 Request 的資料,但是傳遞過程可以透過第一次要求連接時的 Request 中觀察。
關於 WebSocket 傳送資料時,除了字串外還可以使用 USVString、ArrayBuffer、Blod、ArrayBufferView …,另外傳送 JSON 時,記得在 send 中做 JSON.stringify ,接收到時再用 JSON.parse 轉成物件處理。
參考:
Heroku | 搭配 Git 在 Heroku 上部署網站的手把手教學
JavaScript | WebSocket 讓前後端沒有距離
https://www.npmjs.com/package/ws
六角學院課程