文章出處

基于 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 這個框架

http://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地址


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜

    大師兄 發表在 痞客邦 留言(0) 人氣()