我的编程空间,编程开发者的网络收藏夹
学习永远不晚

socket.io学习教程之深入学习篇(三)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

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() }) })

与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) {}); 

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对编程网的支持。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

socket.io学习教程之深入学习篇(三)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

socket.io学习教程之深入学习篇(三)

前言 socket.io提供了基于事件的实时双向通讯,本文深入的介绍了socket.io,下面来看看详细的内容吧。 静态文件socket.io默认情况下会通过socket.io-client包提供socket.io.min.js和socke
2022-06-04

socket.io学习教程之基本应用(二)

前言 Socket.IO支持及时、双向与基于事件的交流。它可以在每个平台、每个浏览器和每个设备上工作,可靠性和速度同样稳定。实时分析:将数据推送到客户端,这些客户端会被表示为实时计数器,图表或日志客户。实时通信和聊天:只需几行代码便可写成一
2022-06-04

socket.io学习教程之基础介绍(一)

前言Web端与服务器间的实时数据传输的是一个很重要的需求,但最早只能通过AJAX轮询询实现。在WebSocket标准没有推出之前,AJAX轮询是唯一可行的方式(通过Flash浏览器也可以,但这里不做讨论)。AJAX轮询原理是设置定时器,定时
2022-06-04

Kotlin学习教程(三)

前面介绍了基本语法和编码规范后,接下来学习下基本类型。在Kotlin中,所有东西都是对象,在这个意义上讲我们可以在任何变量上调
Kotlin学习教程(三)
2024-11-04

Netty学习教程之基础使用篇

什么Netty?Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。也就是说,Netty 是一个基于NIO的客户、服务器端编程框架
2023-05-31

深入学习java之泛型

概念:泛型,即“参数化类型”。就是将原来具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。本质:为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体
深入学习java之泛型
2017-12-30

Nodejs学习笔记之入门篇

分享第一篇,关于 NodeJS —— Javascript 的常用知识以及如何从 Javascript 开发者过渡到 NodeJS 开发者(不会介绍具体的框架)。在读本文前,希望你对 javascript 有一些初步的认识。 Javascr
2022-06-04

python入门学习之变量篇

【前言】在公司内部wiki上看到一个不错的学习网站,遂开始了我这慢悠悠的学习之旅。网站链接:https://www.codecademy.com1.理解布尔值一种数据类型。简单来说,正如你家里的电灯有开关两种状态一样,布尔值同样也有两个值,
2023-01-31

vuex学习进阶篇之getters的使用教程

getters用于获取state里的数据,它类似于计算属性,如果要获取的数据并没有发生变化的话,就会返回缓存的数据,下面这篇文章主要给大家介绍了关于vuex学习进阶篇之getters的使用教程,需要的朋友可以参考下
2022-11-13

Python装饰器入门学习教程(九步学习)

装饰器(decorator)是一种高级Python语法。装饰器可以对一个函数、方法或者类进行加工。在Python中,我们有多种方法对函数和类进行加工,比如在Python闭包中,我们见到函数对象作为某一个函数的返回结果。相对于其它方式,装饰器
2022-06-04

深入学习java之transient关键字

对于transient这个关键字或许很陌生基本没怎么用过,但是transient关键字在java中却起到了不可或缺的地位!在学习java的过程中transient关键字少见的原因其实离不开它的作用:transient关键字的主要作用就是让某些被transien
深入学习java之transient关键字
2021-04-10

spring cloud学习入门之config配置教程

前言本文主要给大家分享了关于spring cloud的入门教程,主要介绍了config配置的相关内容,下面话不多说了,来一起看看看详细的介绍吧。简介Spring cloud config 分为两部分 server client conf
2023-05-31

机器学习 | PyTorch简明教程下篇

接着上篇《PyTorch简明教程上篇》,继续学习多层感知机,卷积神经网络和LSTMNet。
机器学习2024-11-30

机器学习 | PyTorch简明教程上篇

前面几篇文章介绍了特征归一化和张量,接下来开始写两篇PyTorch简明教程,主要介绍PyTorch简单实践。

编程热搜

目录