1. 程式人生 > 實用技巧 >3分鐘接入socket.io使用

3分鐘接入socket.io使用

WebSocket 簡介

傳統的客戶端和伺服器通訊協議是HTTP:客戶端發起請求,服務端進行響應,服務端從不主動勾搭客戶端。

這種模式有個明顯軟肋,就是同步狀態。而實際應用中有大量需要客戶端和伺服器實時同步狀態的場景,比如聊天室、股票行情、線上共享文件等都需要客戶端實時拿到伺服器的最新狀態。

針對這種實時同步的需求,一種簡單的方式是輪詢,比如每隔5s發一次http請求去拿伺服器最新的狀態資料。但這種方式會存在資料延遲,浪費頻寬等副作用。

更完美的方式是使用WebSocket,瀏覽器原生支援,W3C標準協議,客戶端和伺服器建立永續性連線可以互發訊息。

socket.io 簡介

socket.io 是一個類庫,內部封裝了WebSocket,可以在瀏覽器與伺服器之間建立實時通訊。

如果某些舊版本的瀏覽器不支援WebSocket,socket.io會使用輪詢代替。另外它還具有可傳送二進位制訊息、多路複用、建立房間等特性,因此相比直接使用原生WebSocket,socket.io是更好的選擇。

開發一個實時應用主要分兩部分:服務端和客戶端,socket.io分別提供了相應的npm包供我們方便地呼叫。

接下來就通過一個生動形象且有趣的栗子分別介紹這兩大塊。

現在假設李白,瑤,呂布,后羿,貂蟬5個人加入了一個叫 KPL 的房間,在文章結束時我們將擁有一個麻雀雖小五臟俱全的峽谷英雄線上聊天室

服務端api

首先安裝socket.io提供的服務端npm包:

npm i socket.io

可以與 Express 框架配合使用:

const http = require('http')
const app = require('express')()
const server = http.createServer(app)
const io = require('socket.io')(server)
server.listen(3000)

也可以與 Koa 框架配合使用

const http = require('http')
const Koa = require('koa')
const app = new Koa()
const server = http.createServer(app.callback())
const io = require('socket.io')(server)
server.listen(3000)

使用起來就是這麼簡單。接下來就可以寫業務邏輯啦

io.on('connect', client => { // client 即是連線上來的一個客戶端
  console.log(client.id) // id 是區分客戶端的唯一標識

  client.on('disconnect', () => {}) // 客戶端斷開連線時呼叫(可能是關掉頁面,網路不通了等)
})

connectdisconnect 是 socket.io 內建的事件型別,用於在客戶端連線和斷開的時候做一些事情。

在客戶端建立連線時需要把他們加入到一個房間裡去,類似建立了一個聊天室

  console.log(client.id)
+ client.join('KPL') // 將客戶端加入到 KPL 房間內
  client.on('disconnect', () => {})

緊接著瑤進來秒發了首條訊息:我打野,不給就送

伺服器在收到這條振奮人心的訊息後需要立即同步給其他四位隊友

  client.join('KPL')
+ client.on('talk', message => {
+   client.to('KPL').emit('talk', message) // 傳送給房間裡的每個人,除了傳送者
+ })
  client.on('disconnect', () => {})

服務端的功能到這基本上就開發完了。建立了一個房間,並在收到成員訊息時立即同步給房間裡的其他成員

客戶端api

socket.io 為客戶端提供了另一個npm包,直接安裝

npm i socket.io-client

接下來就可以在頁面上建立到伺服器的連線啦

import io from 'socket.io-client'

const socket = io() // 建立連線

向伺服器傳送訊息

  const socket = io()
+ socket.emit('talk', '我打野,不給就送')

接收伺服器發來的訊息

  const socket = io()
+ socket.on('talk', message => {
+ })

李白看到了瑤的訊息,強忍住問候對方家人的衝動,像哄那啥似地說道:

  socket.on('talk', message => {
+   socket.emit('talk', '你買個石頭騎在我頭上他不香麼')
  })

客戶端的功能到這基本上也開發完了。核心api就是on和emit用於收發訊息,既簡單又優雅。

最後

至此一個可以實時傳送接收訊息的聊天室就完成了,雖然簡陋,但核心功能完備。

瑤最終倔強地打了野,李白選擇了上路,3分鐘被對面捶到高地,后羿在家裡等鳥,呂布和貂蟬躲在藍buff旁邊的草叢裡聊天,就這樣在李白和瑤互相拉票舉報對方的全域性訊息中游戲結束