首頁 web前端 js教程 node.js中socket.io學習教學介紹(三)

node.js中socket.io學習教學介紹(三)

May 03, 2017 am 10:02 AM

這篇文章更加深入的給大家介紹了socket.io的相關資料,之前已經介紹了socket.io的基本教程和應用,本文更為深入的來介紹下socket.io的使用,需要的朋友可以參考借鑒,下面來一起看看吧。

前言

socket.io提供了基於事件的即時雙向通訊,本文深入的介紹了socket.io,下面來看看詳細的內容吧。

靜態檔案

socket.io預設會透過socket.io-client套件提供socket.io.min. js和socket.io.js.map下載

執行實例app.js

let app = require('http').createServer() 
let io = require('socket.io')(app)

app.listen(3000);
登入後複製

瀏覽器存取http://localhost:3000/socket.io/socket.io. js可以載入壓縮的源碼,訪問http://localhost:3000/socket.io/socket.io.js.map載入sourcemap

我們可以改變這個行為

#停用socket.io.js下載

方法1: 實例化時傳入控制參數serveClient值false

let io = require('socket.io')(app, { 
 serveClient: false
})
登入後複製

方法2: 呼叫函數serverClient

let app = require('http').createServer() 
let io = require('socket.io')() 
io.serveClient(false) 
io.listen(app) // 或者io.attach(app)
登入後複製

如果在呼叫函數前服務已綁定http.Server,該方法將不起作用

停用後再次訪問將提示{" code":0,"message":"Transport unknown"}

#修改靜態檔案路徑

socket. io.js路徑可以改變,其預設路徑為/socket.io。

實例化時傳參

let io = require('socket.io')(app, { 
 path: '/io'
})
登入後複製

呼叫函數path

let app = require('http').createServer() 
let io = require('socket.io')() 
io.path('/io') 
io.listen(app)
登入後複製

如果在呼叫函數前服務已綁定http.Server,該方法將不起作用

安全性原則

socket.io提供了兩個安全性原則

# allowRequest

函數allowRequest有兩個參數,第一個參數為收到的握手包(http.request)對象,作為判斷依據, success), err是錯誤物件,success為boolean, false表示阻止建立連線

前端請求帶上token

let socket = io('http://localhost:3000?token=abc') 
socket.on('connect', () => { 
 console.log('connect')
})
socket.on('connect_error', err => { 
 socket.disconnect()
 console.log('connect_error', err)
})
登入後複製

後端allowRequest根據token判斷是否繼續

let app = require('http').createServer() 
let io = require('socket.io')(app, { 
 allowRequest: (req, cb) => {
 if (req._query && req._query.token === 'abc') return cb(null, true)
 cb(null, false)
 }
});
登入後複製

origins

可以對來源進行限制

1、實例化時限制來源

let app = require('http').createServer() 
let io = require('socket.io')(app, { 
 origins: 'http://localhost:3000'
})
登入後複製

2、origins函數設定來源

#origins函數有兩種形式

origins(string) : 設定運行的來源

##origins(string, fn (err, success)) : 透過函數判斷來源是否允許

io.origins('http://localhost:*')

io.origins((origin, cb) => { 
 if (origin === 'http://localhost:3000/') return cb(null, true)
 cb(null, false)
})
登入後複製

#名稱空間

名稱空間用來對服務端/客戶端的連線隔離,有些地方,也稱呼名稱空間(namespace)為通道(channel)。以下舉例對其意義進行說明

我們需要實作一個協同應用程式,這個應用程式有兩個功能:

  • 協同編輯: 多個使用者可以同時編輯一個文檔

  • 訊息: 用戶間可以發送訊息


#用socket.io實作這個應用,有下列幾種形式

1、完全獨立: 協同編輯有一個獨立服務

edit.socket.test ,訊息系統一個獨立服務message.socket.test

let editSocket = io('edit.socket.test') 
let messageSocket = io('message.socket.test')
登入後複製

2 、名稱空間: 只執行一個獨立服務,透過名稱空間進行隔離

let app = require('http').createServer() 
let io = require('socket.io')(app) 
let editServer = io.of('/edit') 
let messsageServer = io.of('/message') 
editServer.on('connection', socket => { 
 //编辑相关
})
messsageServer.on('connection', socket => { 
 /消息相关
})
登入後複製
let editSocket = io('socket.test/edit') 
let messageSocket = io('socket.test/message')
登入後複製

3、事件名約定: 透過為事件名稱新增進行隔離

let app = require('http').createServer() 
let io = require('socket.io')(app)

io.on('connection', socket => { 
 //编辑相关
 io.emit('edit:test')
 io.on('edit:test', data => {

 })
 //消息相关
 io.emit('message:test')
 io.on('message:test', data => {

 })
}
登入後複製

透過事件名稱約定程式的侵入性太大,不利於分割和重組,不推薦。 而完全獨立的模式需要使用兩個socket連接,即浪費瀏覽器允許的並發連接數,又消耗更多伺服器資源。使用名稱空間即能實現很好的隔離,又不會對資源造成浪費。

預設名稱空間

socket.io實例化時自動綁定路徑為/的名稱空間

let app = require('http').createServer() 
let io = require('socket.io')(app)

io.sockets // io.of('/').sockets 
io.emit // 代理io.of('/').emit, 类似函数有'to', 'in', 'use', 'send', 'write', 'clients', 'compress'
登入後複製

中間件

socket.io的名空間透過use註冊中間件,中間件在客戶端與服務端建立連線成功後, connet事件派發前呼叫一次。

利用中間件資料校驗

io.use((socket, next) => { 
 if (socket.request.headers.cookie) return next()
 next(new Error('Authentication error'))
})
登入後複製

利用中間件擷取或轉換資料

io.use((socket, next) => { getInfo(socket.request .query.id, (err, data) => { if (err) return next(err) socket.custom = data next() }) })<br/>

與allowRequest對比

allowRequest可以進行一些校驗,提取,為什麼還要需要中間件?

  • allowRequest傳入的http.request實例,而中間件出入資料socket實例,socket實例包含request實例,且有更多資訊

  • #中間件直接支援多個非同步流程巢狀,而allowRequest需要自己實作


#與connection事件對比

#connection事件也傳入socket,也可以進行數驗,提取,為什麼還要需要中間件?

  • 中間件直接支援多個非同步流程嵌套,而allowRequest需要自己實作

  • 中间件成功后到connection事件发送成功前,socket.io还做了一些工作,比如把socket实例添加到connected对象中,加入聊天室等。如果因为权限中断连接,在中间件中处理更省资源.

聊天室

聊天室是对当前连接的socket集合根据特定规则进行归组,方便群发消息。可以类比QQ群的概率.

socket.join(&#39;room name&#39;) //进入 
socket.leave(&#39;room name&#39;) //退出
登入後複製
io.to(&#39;some room&#39;).emit(&#39;some event&#39;) // io.to与io.in同义,向某个聊天室的所有成员发送消息
登入後複製

默认聊天室

每个socket在连接成功后会自动创建一个默认个聊天室,这个聊天室的名字是当前socket的id,可以通过默认聊天室实现向特定用户发送消息

socket.on(&#39;say to someone&#39;, (id, msg) => { 
 socket.broadcast.to(id).emit(&#39;my message&#39;, msg)
})
登入後複製

消息发送

应答消息

普通消息不需要回应,而应答消息提供了应答机制

io.on(&#39;connection&#39;, socket => { 
 socket.emit(&#39;an event&#39;, { some: &#39;data&#39; }) //普通消息

 socket.emit(&#39;ferret&#39;, &#39;tobi&#39;, function (data) { //应答消息
 console.log(data); // data will be &#39;woot&#39;
 })
})
登入後複製


socket.on(&#39;ferret&#39;, (name, fn) => { 
 fn(&#39;woot&#39;)
})
登入後複製

压缩

socket.compress(true)启用压缩,调用后当前连接的所有数据在传递给客户端前都会进行压缩

volatile标志

socket.io在正常情况下对发送的消息进行追踪,确保消息发送成功,而设置volatile后发送消息,socket.io不会对消息追踪,消息可能丢失

分类

// 客户端发送消息
socket.emit(&#39;hello&#39;, &#39;can you hear me?&#39;, 1, 2, &#39;abc&#39;);

// 向所有连接的客户端(除了自己)发送消息
socket.broadcast.emit(&#39;broadcast&#39;, &#39;hello friends!&#39;);

// 向game聊天室发送消息,自己不算
socket.to(&#39;game&#39;).emit(&#39;nice game&#39;, "let&#39;s play a game");

// 同时向game1和game2聊天室发送消息,自己不算
socket.to(&#39;game1&#39;).to(&#39;game2&#39;).emit(&#39;nice game&#39;, "let&#39;s play a game (too)");

// 向game聊天室的所有人发送消息
io.in(&#39;game&#39;).emit(&#39;big-announcement&#39;, &#39;the game will start soon&#39;);

// 发送消息到<socketid>客户端
socket.to(<socketid>).emit(&#39;hey&#39;, &#39;I just met you&#39;);
// 发送应答消息
socket.emit(&#39;question&#39;, &#39;do you think so?&#39;, function (answer) {});
登入後複製

以上是node.js中socket.io學習教學介紹(三)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

圖文詳解Node V8引擎的記憶體和GC 圖文詳解Node V8引擎的記憶體和GC Mar 29, 2023 pm 06:02 PM

這篇文章帶大家深入了解NodeJS V8引擎的記憶體和垃圾回收器(GC),希望對大家有幫助!

一文聊聊Node中的記憶體控制 一文聊聊Node中的記憶體控制 Apr 26, 2023 pm 05:37 PM

基於無阻塞、事件驅動建立的Node服務,具有記憶體消耗低的優點,非常適合處理海量的網路請求。在海量請求的前提下,就需要考慮「記憶體控制」的相關問題了。 1. V8的垃圾回收機制與記憶體限制 Js由垃圾回收機

聊聊如何選擇一個最好的Node.js Docker映像? 聊聊如何選擇一個最好的Node.js Docker映像? Dec 13, 2022 pm 08:00 PM

選擇一個Node的Docker映像看起來像是小事,但是映像的大小和潛在漏洞可能會對你的CI/CD流程和安全造成重大的影響。那我們要如何選擇一個最好Node.js Docker映像呢?

Node.js 19正式發布,聊聊它的 6 大功能! Node.js 19正式發布,聊聊它的 6 大功能! Nov 16, 2022 pm 08:34 PM

Node 19已正式發布,以下這篇文章就來帶大家詳解了解Node.js 19的 6 大特性,希望對大家有幫助!

深入聊聊Node中的File模組 深入聊聊Node中的File模組 Apr 24, 2023 pm 05:49 PM

文件模組是對底層文件操作的封裝,例如文件讀寫/打開關閉/刪除添加等等文件模組最大的特點就是所有的方法都提供的**同步**和**異步**兩個版本,具有sync 字尾的方法都是同步方法,沒有的都是異

一起聊聊Node中的事件循環 一起聊聊Node中的事件循環 Apr 11, 2023 pm 07:08 PM

事件循環是 Node.js 的基本組成部分,透過確保主執行緒不被阻塞來實現非同步編程,了解事件循環對建立高效應用程式至關重要。以下這篇文章就來帶大家深入了解Node中的事件循環 ,希望對大家有幫助!

聊聊Node.js中的 GC (垃圾回收)機制 聊聊Node.js中的 GC (垃圾回收)機制 Nov 29, 2022 pm 08:44 PM

Node.js 是如何做 GC (垃圾回收)的?下面這篇文章就來帶大家了解一下。

聊聊用pkg將Node.js專案打包為執行檔的方法 聊聊用pkg將Node.js專案打包為執行檔的方法 Dec 02, 2022 pm 09:06 PM

如何用pkg打包nodejs可執行檔?以下這篇文章跟大家介紹一下使用pkg將Node專案打包為執行檔的方法,希望對大家有幫助!

See all articles