前言
socket.io提供了基于事件的实时双向通讯,本文深入的介绍了socket.io,下面来看看详细的内容吧。
静态文件
socket.io默认情况下会通过socket.io-client包提供socket.io.min.js和socket.io.js.map下载
运行实例app.js
浏览器访问http://localhost:3000/socket.io/socket.io.js可以加载压缩的源码,访问http://localhost:3000/socket.io/socket.io.js.map加载sourcemap
我们可以改变这种行为
禁用socket.io.js下载
方法1: 实例化时传入控制参数serveClient值false
如果在调用函数前服务已绑定http.Server
,该方法将不起作用
禁用后再次访问将提示{"code":0,"message":"Transport unknown"}
修改静态文件路径
socket.io.js路径可以改变,其默认路径为/socket.io。
实例化时传参
如果在调用函数前服务已绑定http.Server
,该方法将不起作用
安全策略
socket.io提供了两种安全策略
allowRequest
函数allowRequest有两个参数,第一个参数为收到的握手包(http.request
)对象,作为判断依据,success),err是错误对象,success为boolean,false表示阻止建立连接
前端请求带上token
后端allowRequest根据token判断是否继续
origins
可以对源进行限制
1、实例化时限制源
2、origins函数设置源
origins函数有两种形式
origins(string)
: 设置运行的源
origins(string,fn(err,success))
: 通过函数判断源是否允许
名称空间
名称空间用来对服务端/客户端的连接隔离,有些地方,也称呼名称空间(namespace)为通道(channel)。下面举例对其意义进行说明
我们需要实现一个协同应用,这个应用有两个功能:
用socket.io实现这个应用,有如下几种形式
1、完全独立: 协同编辑有一个独立服务edit.socket.test
,消息系统一个独立服务message.socket.test
3、事件名约定: 通过为事件名添加进行隔离
//编辑相关
io.emit('edit:test')
io.on('edit:test',data => {
})
//消息相关
io.emit('message:test')
io.on('message:test',data => {
})
}
通过事件名约定程序的侵入性太大,不利于拆分和重组,不推荐。 而完全独立的模式需要使用两个socket连接,即浪费浏览器允许的并发连接数,又更多消耗服务器资源。使用名称空间即能实现很好的隔离,又不会对资源造成浪费。
默认名称空间
io.emit // 代理io.of('/').emit,类似函数有'to','in','use','send','write','clients','compress'
中间件
socket.io的名空间通过use注册中间件,中间件在客户端与服务端建立连接成功后,connet事件派发前调用一次。
利用中间件数据校验
利用中间件提取或转换数据 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在连接成功后会自动创建一个默认个聊天室,这个聊天室的名字是当前socket的id,可以通过默认聊天室实现向特定用户发送消息
消息发送
应答消息
普通消息不需要回应,而应答消息提供了应答机制
socket.emit('ferret','tobi',function (data) { //应答消息
console.log(data); // data will be 'woot'
})
})
压缩
socket.compress(true)
启用压缩,调用后当前连接的所有数据在传递给客户端前都会进行压缩
volatile标志
socket.io在正常情况下对发送的消息进行追踪,确保消息发送成功,而设置volatile后发送消息,socket.io不会对消息追踪,消息可能丢失
分类
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');
// 发送消息到
socket.to(
// 发送应答消息
socket.emit('question','do you think so?',function (answer) {});
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对编程之家的支持。