基於 nodejs 的 webSockt (socket.io)

SmallW發表於2017-12-06

基於 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: 通訊模型

基於 nodejs 的 webSockt (socket.io)

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地址

相關文章