socket.io学习教程之深入学习篇(三)
发布时间 - 2026-01-11 00:54:19 点击率:次前言

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() }) })
与allowRequest对比
allowRequest可以进行一些校验,提取,为什么还要需要中间件?
- allowRequest传入的http.request实例,而中间件出入数据socket实例,socket实例包含request实例,且有更多信息
- 中间件直接支持多个异步流程嵌套,而allowRequest需要自己实现
与connection事件对比
connection事件也传入socket,也可以进行数验,提取,为什么还要需要中间件?
- 中间件直接支持多个异步流程嵌套,而allowRequest需要自己实现
- 中间件成功后到connection事件发送成功前,socket.io还做了一些工作,比如把socket实例添加到connected对象中,加入聊天室等。如果因为权限中断连接,在中间件中处理更省资源.
聊天室
聊天室是对当前连接的socket集合根据特定规则进行归组,方便群发消息。可以类比QQ群的概率.
socket.join('room name') //进入
socket.leave('room name') //退出
io.to('some room').emit('some event') // io.to与io.in同义,向某个聊天室的所有成员发送消息
默认聊天室
每个socket在连接成功后会自动创建一个默认个聊天室,这个聊天室的名字是当前socket的id,可以通过默认聊天室实现向特定用户发送消息
socket.on('say to someone', (id, msg) => {
socket.broadcast.to(id).emit('my message', msg)
})
消息发送
应答消息
普通消息不需要回应,而应答消息提供了应答机制
io.on('connection', socket => {
socket.emit('an event', { some: 'data' }) //普通消息
socket.emit('ferret', 'tobi', function (data) { //应答消息
console.log(data); // data will be 'woot'
})
})
socket.on('ferret', (name, fn) => {
fn('woot')
})
压缩
socket.compress(true)启用压缩,调用后当前连接的所有数据在传递给客户端前都会进行压缩
volatile标志
socket.io在正常情况下对发送的消息进行追踪,确保消息发送成功,而设置volatile后发送消息,socket.io不会对消息追踪,消息可能丢失
分类
// 客户端发送消息
socket.emit('hello', 'can you hear me?', 1, 2, 'abc');
// 向所有连接的客户端(除了自己)发送消息
socket.broadcast.emit('broadcast', 'hello friends!');
// 向game聊天室发送消息,自己不算
socket.to('game').emit('nice game', "let's play a game");
// 同时向game1和game2聊天室发送消息,自己不算
socket.to('game1').to('game2').emit('nice game', "let's play a game (too)");
// 向game聊天室的所有人发送消息
io.in('game').emit('big-announcement', 'the game will start soon');
// 发送消息到<socketid>客户端
socket.to(<socketid>).emit('hey', 'I just met you');
// 发送应答消息
socket.emit('question', 'do you think so?', function (answer) {});
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对的支持。
# socket.io教程
# socket.io
# 教程
# node.js
# socket.io学习教程之基本应用(二)
# socket.io学习教程之基础介绍(一)
# node.js中的Socket.IO使用实例
# node.js中Socket.IO的进阶使用技巧
# 基于socket.io和node.js搭建即时通信系统
# node.js中的socket.io入门实例
# 使用Angular和Nodejs、socket.io搭建聊天室及多人聊天室
# node中socket.io的事件使用详解
# node.js中使用socket.io的方法
# node.js中的socket.io的广播消息
# 聊天室
# 发送消息
# 客户端
# 多个
# 绑定
# 将不
# 服务端
# 安全策略
# 情况下
# 加载
# 有两个
# 很好
# 第一个
# 不需要
# 两种
# 我们可以
# 可以通过
# 对其
# 太大
# 会对
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
微信小程序 scroll-view组件实现列表页实例代码
西安市网站制作公司,哪个相亲网站比较好?西安比较好的相亲网站?
JS碰撞运动实现方法详解
怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?
Laravel Fortify是什么,和Jetstream有什么关系
高防服务器如何保障网站安全无虞?
Win11怎么设置默认图片查看器_Windows11照片应用关联设置
如何在阿里云虚拟主机上快速搭建个人网站?
如何在IIS7中新建站点?详细步骤解析
如何在宝塔面板中创建新站点?
如何在腾讯云免费申请建站?
实现点击下箭头变上箭头来回切换的两种方法【推荐】
Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)
Laravel怎么解决跨域问题_Laravel配置CORS跨域访问
Laravel怎么使用Blade模板引擎_Laravel模板继承与Component组件复用【手册】
谷歌浏览器如何更改浏览器主题 Google Chrome主题设置教程
百度浏览器ai对话怎么关 百度浏览器ai聊天窗口隐藏
如何快速使用云服务器搭建个人网站?
如何在阿里云ECS服务器部署织梦CMS网站?
如何快速生成可下载的建站源码工具?
HTML5空格和margin有啥区别_空格与外边距的使用场景【说明】
如何续费美橙建站之星域名及服务?
Laravel如何从数据库删除数据_Laravel destroy和delete方法区别
使用spring连接及操作mongodb3.0实例
Laravel如何使用Collections进行数据处理?(实用方法示例)
深圳网站制作培训,深圳哪些招聘网站比较好?
如何在宝塔面板创建新站点?
Laravel如何配置.env文件管理环境变量_Laravel环境变量使用与安全管理
Win11怎么开启自动HDR画质_Windows11显示设置HDR选项
laravel怎么为API路由添加签名中间件保护_laravel API路由签名中间件保护方法
如何确保西部建站助手FTP传输的安全性?
百度输入法ai组件怎么删除 百度输入法ai组件移除工具
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?
Laravel如何与Docker(Sail)协同开发?(环境搭建教程)
phpredis提高消息队列的实时性方法(推荐)
Laravel如何实现事件和监听器?(Event & Listener实战)
Bootstrap整体框架之JavaScript插件架构
Laravel怎么判断请求类型_Laravel Request isMethod用法
免费制作统计图的网站有哪些,如何看待现如今年轻人买房难的情况?
javascript中对象的定义、使用以及对象和原型链操作小结
Android中Textview和图片同行显示(文字超出用省略号,图片自动靠右边)
网站制作软件有哪些,制图软件有哪些?
linux top下的 minerd 木马清除方法
Thinkphp 中 distinct 的用法解析
Laravel如何使用Facades(门面)及其工作原理_Laravel门面模式与底层机制
如何快速辨别茅台真假?关键步骤解析
移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?
Python函数文档自动校验_规范解析【教程】
如何解决hover在ie6中的兼容性问题

