Websocket是一種網路傳輸協定,可以在TCP連接上全雙工通訊,允許伺服器端主動向客戶端推播資料,只要一次的交握,就可以建立不中斷的連接,以進行雙工通訊。
例如為了取得數個球場上比賽的即時分數,因為每個球場比賽得分的時間都不相同,所以使用的方式是在client端每隔幾秒就向Server發送一次http request,向Server取回最新的訊息。
若改以Websocket,因為可以保持連線,所以不必像http request每一次的連線,都需要重送header等重覆的資料,可加快傳輸的速度。
另外,Websocket因為可以由Server來廣播資料,所以當server收到來自A球場的比數時,可以同時將比數發送給B球場、C球場的client。
以http request的方式,必需讓A、B、C球場每隔數秒就要連線一次,但是每次的連線都不一定會有新的資料,這樣的做法會增加Server的負擔。
以下是我測試Websocket的程式,我用node.js來架設server。
node.js:安裝ws套件,npm install ws
建立app.js,內容如下:
//import ws 套件
const SocketServer = require('ws').Server
const express = require('express')
const path = require('path')
//設定port
const PORT = 80
const routeAPI = express.Router();
const app = express()
app.use('/', express.static(__dirname + '/'));
routeAPI.route('/')
.get((req, res) => {
res.status(200).send("OK");
})
routeAPI.route('/test01')
.get((req, res) => {
res.sendFile('test01.html', { root: path.join(__dirname) });
})
app.use('/', routeAPI);
//創建 express 物件,綁定監聽 port , 設定開啟後在 console 中提示
const server = app.listen(PORT, () => {
console.log("Listening on ${PORT}")
})
//將 express 交給 SocketServer 開啟 WebSocket 的服務
const ws = new SocketServer({ server })
//當client連線時
ws.on('connection', ws_conn => {
console.log('Client connected')
//收到client資料時
ws_conn.on("message", data => {
//client資料是Buffer格式,需要轉成字串
data = data.toString()
console.log(data)
// 發送消息給client
ws_conn.send("server return:" + data)
//取得所有連接中的 client
let clients = ws.clients
//發送資料至每個client
clients.forEach(client => {
client.send("server return :" + data)
})
})
})
//當連線關閉
ws.on('close', () => {
console.log('Close connected')
})
建立test01.html,內容如下:
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title> WebSocket Test</title>
</head>
<body>
<textarea id="txtShow" disabled></textarea>
<input id="txtInput" type="text">
<button id="btnSend">送出</button>
<button id="btnClose">關閉</button>
</body>
</html>
<script src="jquery-3.4.1.min.js"></script>
<script>
// 建立 WebSocket (本例 server 端於本地運行)
let url = 'ws://192.192.192.10:9910'
var ws = new WebSocket(url)
// 監聽連線狀態
ws.onopen = () => {
console.log('open connection')
}
ws.onclose = () => {
console.log('close connection');
}
//接收 Server 發送的訊息
ws.onmessage = event => {
console.dir(event)
let txt = event.data
$("#txtShow").val(txt)
}
$('#btnSend').on('click',() => {
let txt = $('#txtInput').val()
//發送訊息
ws.send(txt)
})
$("#btnClose").on('click',() => {
ws.close()
})
</script>