WebSocket in NodeJS and VueJS
Websocket簡介
根據wiki的定義,websocket是一個基於TCP的網路傳輸協定。在一般的 GET/POST http request中,是等傳輸完資料後、TCP會經過四次揮手後斷開連接;但在WebSocket協定中,只要客戶端和服務端經過TCP握手連接後,兩者就可以建立長時間的連接。
為何要有websocket的協定呢?主要是因為HTTP協議的缺陷:HTTP請求只能由客戶端發起。這樣一來,如果客戶端需要響應服務端的變化,就必須要在一個間隔時間內不斷發起請求、「監聽」服務端的變化;而有了websocket,便可以建立了長時間的連接:客戶端發起一次請求、建立連接,而後只要服務端有數據或是什麼的變化,服務端便可以透過該連接直接傳遞、客戶端進而響應該變化。
在NodeJS中使用websocket
從Awesome List of websocket for NodeJS可以看到,NodeJS有許多websocket的依賴;然後根據starts數來排名的話,socket.io和websockets/ws與其他依賴有著很大的差距(57.5k and 19.4k on 20230131),因此先以這兩者和exporess
來Demo看看。
Socket.io
// app.js const express = require('express') const http = require('http') const socket = require('socket.io') const app = express() // use express to handle http server const server = http.createServer(app) const io = socket(server) // while socket connect, send a 'hello world text' const onConnection = (socket) => { socket.send("hello world ") console.log('Socket.io init success') } io.on("connection", onConnection) server.listen(3000, () => { console.log('Server listening at port 3000'); })
ws
// app.js const express = require('express') const { WebSocketServer } = require('ws') const app = express() // use express to handle http server const server = http.createServer(app) const wss = new WebSocketServer({ server }) wss.on('connection', ws => { ws.send("hello world ") console.log('Socket.io init success') }) server.listen(3000, () => { console.log('Server listening at port 3000'); })
可以看到,兩者在NodeJS的寫法上是沒有太大的區別,差別應該是在包的體積大小和性能方面。(socket.io
: 276.6k, ws
:43.8K)
在前端使用Websocket(以Vue為例)
- Socket.io
Socket.io之前最吸引人的地方,就是它在服務端和瀏覽器端都有做封裝,因此可以直接拿來用:
// useSocket.ts
import { io } from 'socket.io-client'
export default function useSocket() {
const socket = io('ws://localhost:3000')
return {
socket,
}
}
// Demo.vue
import useSocket from '../utils/useSocket'
...
setup(){
const { socket } = useSocket()
onMounted(() => {
socket.on('connect', (data) => {
console.log(data)
})
})
return {}
}
- ws
從官方文件和網路上其他人的Demo來看,目前ws還沒有封裝客戶端的使用,所以只能用瀏覽器原生的 WebSocket
來做封裝;最簡單的話就是直接拿原生API來用
// useSocket.ts
export default function useSocket() {
const socket = new WebSocket('ws://localhost:3000')
return {
socket,
}
}
// Demo.vue
import useSocket from '../utils/useSocket'
...
setup(){
const { socket } = useSocket()
onMounted(() => {
socket.onmessage( (event) =>{
console.log(`socket data:${event.data}`)
} )
})
return {}
}
ChangeLog
- 20230131-初稿