Flask-Socketio的使用
WebSocket
WebSocket是一种网络协议,可以用来实现在客户端和服务器之间的双向实时通信,前端可以向后端发送请求,同时后端也可以向前端进行实时数据推送。传统的HTTP协议是无状态的,每次请求都需要重新建立连接,而利用WebSocket可以在建立连接之后保持连接状态,双方可以随时发送信息。
在一个实时的Web应用程序中,我们可以使用Vue作为前端框架,使用Flask作为后端框架。前后端都有相关的工具来支持WebSocket,使得开发WebSocket应用更加容易。
案例介绍
相关概念
在介绍案例之前,我们可以简单了解一下WebSocket的工作原理。WebSocket可以实现服务器和客户端之间的双向通信,我们可以想象是在双方之间建立了一个通道,前后端都可以进行信息发送和信息接收。具体来说,我们会在后面见到emit
和on
的操作,分别代表发送信息以及接收信息。
如果客户端想要使用websocket接受服务器推送的话,Socketio是一个不错的选择。Socket.io将Websocket、轮询机制以及其它的实时通信方式(ajax等)封装成了通用的接口,并且在服务端也实现了这些实时机制的相应代码。所以,使用Socket.io便不需要担心浏览器兼容问题。
在socketio中还有两个重要的概念,分别为namespace
和event
,前后端如果要进行双向通信,这些信息应该同属于一个namespace。而event则是在信息发送和接收的时候使用到,我们可以触发一个event,也可以监听一个event,这样就形成了一个通道,使得数据能够正确传递。在后面我们也可以在代码中看到对应的概念。
Flask SocketIO
Flask SocketIO是在Flask框架中对WebSocket的支持,通过它我们能够在Flask中很方便地完成WebSocket应用的编写。可以通过pip来进行依赖的安装:
1 |
|
之后,我们可以通过如下的代码来获取对应的SocketIO对象。这里为了解决跨域问题,我们使用了CORS以及cors_allowed_origins='*'
。
1 |
|
下一步,我们可以完成一个通信方法。可以看到,在代码中我们指定了namespace
为/api
,同时还调用了SocketIO对象的on
和emit
方法。首先,后端会监听/api
下的my event
事件,如果监听到了,就会触发该函数。在函数中,我们可以接收推送的信息data,然后后端调用emit
方法,触发my response
事件,同时传递数据。这里传递的数据就是在得到的data基础上进行了一层包装。
1 |
|
SocketIO应用的启动和传统的Flask有所区别,需要使用SocketIO
对象来run。如果使用的是dev模式,则需要额外增加属性allow_unsafe_werkzeug=True
1 |
|
Vue 前端展现
在前端我们同样需要SocketIO的支持。这里我们使用Vue框架作为前端的实现。在Vue中有两种方式来使用SocketIO,一种是直接使用官方包SocketIO
,第二种是使用VueSocketio
。第二种方式是对SocketIO的一层封装,更适合在Vue项目中使用,不过在案例实现的过程中,第二种方法会有版本不匹配的问题出现,因此这里还是选择使用第一种方式。
首先需要通过npm安装相关依赖:
1 |
|
之后,我们可以在需要使用WebSocket的组件中进行使用。下面来介绍一个简单案例。首先展现组件的完整代码:
1 |
|
在测试组件中,我们的data中返回一个data字段,用于承接后端推送的信息,并将其渲染在页面中。在组件mounted的声明周期,我们通过io
获取一个SocketIO
对象,然后通过该对象分别调用了emit以及on方法。注意这里在对象初始化的时候,我们已经在url中指定了namespace
,实际上namespace就相当于path的拼接。
对应到前面Flask的案例代码,首先前端通过emit
触发my event
事件传递数据{'data': "data from fronend"}
,后端flask监听了对应namespace下的该事件,于是会在控制台中进行打印,同时调用emit
方法触发my response
事件,向前端传送信息。前端使用了on
方法来监听my response
事件,因此能够得到后端传送来的数据,同时更新this.data
,进行页面渲染。
最终我们可以在前端页面上看见如下效果:
动态推送
上面的案例中,后端只是向前端完成了一次简单的数据推送,更常见的场景是后端持续向前端进行数据推送,我们可以简单修改上面的示例代码来模拟对应场景:
1 |
|
之后在前端页面上,我们就可以看到动态变化的信息了。
注意事项
在使用过程中,可能出现如下异常情况。在Flask后端中出现下面的提示信息,同时前端控制台上会一直提示400以及跨域错误。
1 |
|
这是因为相关依赖的版本不能匹配。在使用过程中,前后端使用的SocketIO以及相关依赖的版本需要能够匹配上,否则会无法工作。匹配的版本可以在Introduction — Flask-SocketIO documentation中进行查看,目前的对应关系如下所示。
JavaScript Socket.IO version | Socket.IO protocol revision | Engine.IO protocol revision | Flask-SocketIO version | python-socketio version | python-engineio version |
---|---|---|---|---|---|
0.9.x | 1, 2 | 1, 2 | Not supported | Not supported | Not supported |
1.x and 2.x | 3, 4 | 3 | 4.x | 4.x | 3.x |
3.x and 4.x | 5 | 4 | 5.x | 5.x | 4.x |