基於 nodejs 的 webSockt (socket.io) 理解
本文的業務基礎是在基於 nodejs 的 socket.io 的直播間聊天室(IM)應用來的。
專案中具體的 框架如下 express + mongodb + socket.io
在介紹 socket.io 之前,我們有必要對 webSocket 進行根本的原理的理解。
複製程式碼
一、webSocket 的前生今世
1、什麼是 webSocket?
2、如何去用?
3、經常使用的場景?
4、需要注意的地方
好了,下面我們就按照上面 提到的四點來進行分析。
複製程式碼
1、 什麼是 websocket
官方文件解讀: webSocket
這個是 MDN 的官方文件。詳細的內容需要讀者自己仔細去閱讀了,筆者這裡只介紹 容易出錯的問題。
1、WebSockets 是一個可以建立和伺服器間進行雙向會話的高階技術。通過這個API你可以向伺服器傳送訊息並接受基於事件驅動的響應,這樣就不用向伺服器輪詢獲取資料了。
當然這個只是說用來解決 不用向伺服器輪詢獲取資料問題。 這麼來說的話其實還是不太夠 ‘官方’。
非官方理解: B/S 結構的軟體專案中,客戶端通過 http、https 等方式獲得伺服器訊息,但是預設的 http 協議只支援 請求響應模式,這種模式簡化了 web 伺服器,減少伺服器負擔,加快網站的響應速度。 但是不能滿足 我們實時訊息推送,聊天室等功能,這個時候 websocket 這個本 作為 unix 程式通訊機制 就被嫁接到了 應用程式間網路通訊,從而就有了如今的 socket
複製程式碼
2、Websocket: 通訊模型
WebSocket是HTML5開始提供的一種瀏覽器與伺服器間進行全雙工通訊的網路技術。依靠這種技術可以實現客戶端和伺服器端的長連線,雙向實時通訊。
特點: 事件驅動、非同步 使用 ws 或者 wss 協議的 socket、 實現真正意義上的 推送功能
這裡的 ws 和 wss 區別跟 http 和 https 的區別一樣(安全性)
缺點就是 相容性(今年已經 2017年了,應該可以不用考慮這個問題了)
複製程式碼
3、 websocket 客戶端
官方文件中回提供系列的 api 具體如下:
分類如下:
a) 連線類:
1、send() 向遠端伺服器傳送資料
2、close() 關閉該websocket連結
b) 監聽函式類:
1、onopen 當網路連線建立時觸發該事件
2、onerror 當網路發生錯誤時觸發該事件
3、onclose 當 websocket 被關閉時觸發該事件
4、onmessage 當 websocket 接收到伺服器發來的訊息的時觸發的事件,也是通訊中最重要的一個監聽事件。 其中 我們可以定義各類 onmessage 事件的 type 從而 擴充套件我們的 onmessage 事件。
c) websocket還定義了一個readyState屬性:
1、CONNECTING(0) websocket正嘗試與伺服器建立連線
2、OPEN(1) websocket與伺服器已經建立連線
3、CLOSING(2) websocket正在關閉與伺服器的連線
4、CLOSED(3) websocket已經關閉了與伺服器的連線
複製程式碼
4、 websocket 服務端
服務端就像是一個分發中心, 但是首先都得通過 connect 建立連線 從而形成 ws 的長連線。
只要 長連線 連線成功,那麼接下來的事情就很好操作了, 比如在服務端 emit 觸發一個事件,那麼在 服務端就需要監聽 on 方法來監聽同一個事件,最後如果需要讓 當前房間(注: 這裡有個 單房間 和 多房間的概念,我們在後面的介紹中會仔細的提到的)內的所有連線使用者都被通知到這則訊息,那麼 在監聽到服務端觸發的訊息的同時,再來觸發一個廣播給 客戶端, 這個時候只要是在當前 ws 連線線上的所有使用者都會被 emit 觸發到這個事件,從而實現了 廣播。
上面的這一長段話,可能暫時不太好理解,但是如果 親手來寫上這麼一個 demo 就會理解很多了。
複製程式碼
二、 基於 nodeJs 的 webSocket 框架 socket.io
socket.io 是這篇文章的主角,因為它對 webSocket 做了一個非常完善的封裝, 並且提出了 多房間 多名稱空間的 概念,讓多聊天室同時存在不再是一個問題,所以,下面就會詳細的來介紹下 socket.io 這個框架
複製程式碼
socket.io 這個是官網
我們在官網中 可以看到非常簡潔的 socket.io 的應用方法。
並且還展示了一個全世界通用的 IM (雖然這裡常常可以看到 f**k xxx)
複製程式碼
好了,下面就針對 這個 socket.io 再進行一個詳細的介紹
1、 Server api
2、 Client api
3、 Rooms and NameSpace
複製程式碼
這要就針對這三個來進行介紹
1、 Server api
服務端初始化 io 物件
複製程式碼
const io = require('socket.io')();
// or
const Server = require('socket.io');
const io = new Server();
複製程式碼
這個時候就需要看 你的後臺 服務的語言, php java nodejs 等等
我是用的 nodejs 所以直接 使用 express or koa2 均可
然後建立 http-server 服務
複製程式碼
const socket = require('socket.io');
var app = express()
var server = http.createServer(app)
io = socket(server)
io.on('connection', function(socket) {
// to do somethings
})
複製程式碼
上面的這個步驟就可以輕鬆的 通過 nodejs + express 建立了一個 socket 服務端的 服務了
複製程式碼
2、 Client api
上面的步驟中已經在 服務端進行了 一些列 的操作 ,這個時候就需要 在服務端 建立 連線
首先是 需要在 前端引用 這個 socket 檔案
複製程式碼
<script src="/socket.io/socket.io.js"></script>
<script>
const socket = io('http://localhost');
</script>
const io = require('socket.io-client');
// or with import syntax
import io from 'socket.io-client';
複製程式碼
然後 建立 連線
複製程式碼
const socket = io();
複製程式碼
然後 觸發監聽 'connection'
複製程式碼
io.on('connection', (socket) => {
let token = socket.handshake.query.token;
// ...
})
複製程式碼
加入這個時候你在 服務端 列印 debug 如果順利 就可以輕鬆 完成了第一個 socket 的連結啦~
複製程式碼
3、 Rooms and NameSpace
最後這裡 介紹到的 rooms 和 namespace 的概念
在多房間 聊天室 中 佔據了很大的作用
其中 介紹下 rooms 的 概念 , 關於 namespace 相關可以到 socket.io 官網中進行檢視
複製程式碼
// 廣播給當前房間除了自己以外的所有人
socket.broadcast.to(roomId).emit('msg', {
// take somethings
})
// 廣播給當前房間中自己
socket.emit('msg', {
// take somethings
})
// 廣播給當前房間的所有人
socket.to(roomId).emit('msg', {
// take somethings
})
複製程式碼
然後再結合上面的 監聽 、 觸發 方法,完成一系列的需求任務。
複製程式碼
恩,今天先到這裡,有什麼問題,可以留言互相學習。 歡迎推薦~~~
附上 github地址