工作记录:Vue项目中使用WebSocket通讯

  • A+
所属分类:Web前端
摘要

以下内容摘自维基百科 : WebSocket是一种网络传输协议 ,可在单个TCP 连接上进行全双工 通信,位于OSI模型 的应用层 。WebSocket协议在2011年由IETF 标准化为RFC 6455 ,后由RFC 7936 补充规范。Web IDL 中的WebSocket API由W3C 标准化。

WebSocket介绍

以下内容摘自维基百科

WebSocket是一种网络传输协议,可在单个TCP连接上进行全双工通信,位于OSI模型应用层。WebSocket协议在2011年由IETF标准化为RFC 6455,后由RFC 7936补充规范。Web IDL中的WebSocket API由W3C标准化。

WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输。

历史

WebSocket最初在HTML5规范中被引用为TCPConnection,作为基于TCP的套接字API的占位符。

 

WebSocket”这个名字是Ian Hickson和Michael Carter之后在 #whatwg IRC聊天室创造的,随后由Ian Hickson撰写并列入HTML5规范,并在Michael Carter的Cometdaily博客上宣布

 

2008年6月,Michael Carter进行了一系列讨论,最终形成了称为WebSocket的协议。

 

2019年12月谷歌浏览器4率先支持WebSocket并默认开启

 

2010年2月WebSocket协议有W3C何WHATWG转移到ETF,并在Ian Hickson的指导下进行了两次修订。

 

2011年12月,WebSocket成为国际通用协议。

背景

WebSocket出现之前,很多网站为了实现推送,所有技术都是使用轮询(每隔一段时间向服务器请求一次最新数据)。这种模式的缺点非常明显:需要不断发送请求,会非常消耗资源。

 

较新的技术是Comet,这种技术虽然能够实现双向通讯,但是也需要频繁发送请求,颇费资源。

 

于是,那个男人出现了,WebSocket只需要浏览器与服务器建立一次连接,便可以实现双向实时通讯。

WebSocket的优点

  • 实时性。个人认为这是最大的优点,因为这个特性,使得WebSocket在很多应用场景变得非常实用。如游戏、实时在线聊天、实时预警等。
  • 较少的控制开销。由于只需要建立一次连接,所以服务器、浏览器开销都较小。并且WebSocket协议数据包头部数据比较小,服务器浏览器只有2-10字节;而浏览器到服务器之间只需要再加4字节作为掩码。
  • 连接状态一直保持。浏览器与服务器之间建立一次有状态连接,除了第一次连接需要携带一些状态数据外,之后的通讯都可以省略。
  • 可支持扩展。用户能够根据WebSocket扩展子协议
  • 更好的压缩效果。相对于HTTP压缩,Websocket在适当的扩展支持下,可以沿用之前内容的上下文,在传递类似的数据时,可以显著地提高压缩率。
  • 与HTTP协议有这较好的兼容性。默认采用80和443端口,握手阶段采用HTTP协议;因此不容易屏蔽,能够通过这种HTTP代理服务器
  • 更好的二进制支持
  • 没有同源限制,麻麻再也不用担心我的跨域问题啦~

支持情况

工作记录:Vue项目中使用WebSocket通讯

可以看到,现代浏览器都支持WebSocket(包括IE老祖宗,二代目Edge更不用说了,纯现代浏览器),移动端支持情况良好,所以还有什么理由不用呢。

原生的WebSocket

因为实际项目中都会使用相关库(如socket.io),所以本文不讨论原生WebSocket(其实原生也很简单),如果有想学习原生WebSocket的同学,可以看MDN中的WebSocket

http://www.ruanyifeng.com/blog/2017/05/websocket.html

 

优秀的WebSocket库

在GitHub上搜索WebSocket,可以看到总共结果有仓库有17K,而JavaScript就有17509个:

  • ws:用于nodeJS的后端WebSocket通讯库
  • SocketJS:多端可用的WebSocket库,涵盖JavaScript(服务端和客户端)、Erlang、Python/Tornado、Java/vert.x
  • socket.io:和SocketJS类似,但是涵盖范围更广:JavaScript(服务端和客户端)、Java、C++、Swift、DartPython、.net。(你问我选哪个?当然是socket.io呀,因为他有vue-socket.io)
  • Total.js:用于服务端的NodeJs库

vue项目的话,选用vue-socket.io简直不要太方便,一次建立链接,应用活动期间随意使用,最关键的是,和vuex配合非常友好。

如何在Vue项目中使用

小例子

 

做了一个小例子,基于vuetify和vue-socket.io的匿名在线聊天系统,可以点击传送门体验WebSocket的快乐。

工作记录:Vue项目中使用WebSocket通讯工作记录:Vue项目中使用WebSocket通讯工作记录:Vue项目中使用WebSocket通讯工作记录:Vue项目中使用WebSocket通讯

WebSocket真的能为所欲为?

工作记录:Vue项目中使用WebSocket通讯

 

安装

可以通过CDN:https://cdn.jsdelivr.net/npm/[email protected]/vue-socket.io-next.js

或者通过包管理器:

yarn add vue-socket.io npm i vue-socket.io

全局使用

在main.ts中添加如下代码:

// 全局使用socket Vue.use(new VueSocketIO({   debug: true, // 开启socket控制台输出   connection: 'http://39.105.103.136:9521/', // 链接地址   // 配置vuex   vuex: {     store,     actionPrefix: 'socket', // socket触发action的前缀     mutationPrefix: 'socket' // socket触发mutation的前缀   } }))

其中配置如下:

参数

类型

默认值

是否必选

描述

debug

Boolean

false

可选

启用控制台输出

connection

String/Socket.io-client

null

必选

WebSocket服务地址或者Socket.io实例

vuex.store

Vuex

null

可选

vuex实例

vuex.actionPrefix

String

null

可选

服务端发送消息是对应vuex的action前缀,其格式如下:

<ACTION_PREFIX><EVENT_NAME>

vuex.mutationPrefix

String

null

可选

服务端发送消息时对应vuex的mutaiton前缀,其格式如下:

<ACTION_PREFIX><EVENT_NAME>

组件中使用

组件中可以使用实例的$socket.emit()方法,其格式如下:

Vue.$socket.emit(eventName: string,eventData:any)

如:

this.$socket.emit('Login', {   username: this.username })

订阅与解除订阅

订阅和解除订阅的方法在sockets属性上,其声明文件如下:

interface Vue {   $socket: SocketIOClient.Socket,     sockets: {       subscribe(eventName: string, handler: socketHandler<Vue>): void,       unsubscribe(eventName: string): void,     } }

所以订阅和接触订阅同理:

this.sockets.subscribe('EVENT_NAME', (data) => {     this.msg = data.message })  this.sockets.unsubscribe('EVENT_NAME')

与vuex结合

如果在main.ts文件中注入了store,vue-socket.io会在接收到相应消息触发相应的mutationaction,其名称格式为<配置的前缀><消息名>

export default class Chat extends VuexModule {   onlineUsers: Users = {}   record: Array<Record> = []    @Mutation   // 服务端消息名为Users,socket是soket提交荷载的前缀,data为服务端发送的数据   socketUsers (data: Users) {     this.onlineUsers = data   }    @Mutation   // 服务端消息名为Record,socket是soket提交荷载的前缀,data为服务端发送的数据   socketRecord (data: Array<Record>) {     this.record = data   } }

虽然能够设置mutationaction,但是最好的方式还是通过设置action

完整例子

完整例子可以看这里

在小程序中如何使用

小程序的话,官方已经给出很详细的文档了,不会的同学可以看这里

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 工作记录:Vue项目中使用WebSocket通讯