在flask中使用WebSocket

孙志
2023-12-01

原文:Easy WebSockets with Flask and Gevent
但是还没有翻译完,后面会进行更新的

我很高兴地介绍Flask-SocketIO,这是一个非常易于使用的扩展,可以在Flask应用程序中启用WebSocket通信。

WebSocket是啥?

WebSocket是HTML5引入的新的通信协议,主要由Web客户端和服务器实现,当然它也可以在Web之外实现。
与HTTP连接不同,WebSocket连接是客户端和服务器之间永久的双向通信通道,其中任何一个都可以启动交换。 一旦建立,连接一直有效,直到其中一方断开连接。
WebSocket连接对于需要以非常低的延迟显示实时信息的游戏或网站很有用。 在此协议存在之前,还有其他效率较低的方法可以实现相同的结果,如Comet
如下浏览器正常WebSocket协议:

  • Chrome 14
  • Safari 6
  • Firefox 6
  • Internet Explorer 10

SocketIO是啥??

SocketIO是一个跨浏览器的Javascript库,它将客户端应用程序从实际的传输协议中抽象出来。 对于现代浏览器,WebSocket协议已经被广泛支持,但是对于没有支持WebSocket 协议的旧版浏览器,SocketIO使用某种方法来在客户端和服务器端之间模拟类似于WebSocket的连接,故对于那些不支持WebSocket 协议的旧版浏览器,使用SocketIO也能够实现同支持WebSocket协议相同的效果。

注:这段话我是我对作者原文的一个意译,我不确定翻译得是否准确,仅供参考,原文是这样的:
For modern browsers the WebSocket protocol is used, but for older browsers that don’t have WebSocket SocketIO emulates the connection using one of the older solutions, the best one available for each given client.

并且SocketIO提供了一个通用的API,隐藏了底层的传输的细节,使用户不用花费多余的精力去关注客户端和服务器的传输机制,因此无论浏览器是否支持WebSocket,在各种情况下,使用SocketIO都能够达到相同的效果。这样就实现了和面向对象中的封装相同的效果 。所以使用SocketIO,您可以非常确定任何浏览器将能够连接到您的应用程序, 对于每个浏览器,将使用最有效的方法。

关于Flask-Sockets

之前,肯尼思·雷茨(Kenneth Reitz)发布了Flask-Sockets,Flask-Sockets是Flask框架的一个扩展,通过它,Flask应用程序可以使用WebSocket。

请读者注意不要将Flask-SocketsFlask-SocketIO弄混淆了,它们是两个不同的Flask扩展。

Flask-Sockets和Flask-SocketIO之间的主要区别在于前者仅仅将WebSocket协议(通过使用gevent-websocket项目)进行包装,因此它只适用于原生支持WebSocket协议的浏览器,对于那些不支持WebSocket协议的较老的浏览器,就无法使用它了。 Flask-SocketIO则不同,通过前面的介绍,读者应该已经知道了它不仅实现了WebSocket协议,并且对于那些不支持WebSocket协议的旧版浏览器,使用它也能够实现相同的效果。
另一个区别是Flask-SocketIO实现了SocketIO Javascript库公开的消息传递协议。 Flask-Sockets只是实现通信通道,发送的是完全取决于应用程序。
Flask-SocketIO还为事件处理程序创建了一个类似flask的常规视图函数的环境,包括创建应用程序和请求上下文。 然而,在文档中会介绍一些重要的例外情形。

Flask-SocketIO的使用

Flask-SocketIO服务器端程序

如下是一个使用了Flask-SocketIO的Flask应用程序。

from flask import Flask, render_template
from flask_socketio import SocketIO, emit

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)

@app.route('/')
def index():
    return render_template('index.html')

@socketio.on('my event', namespace='/test')
def test_message(message):
    emit('my response', {'data': message['data']})

@socketio.on('my broadcast event', namespace='/test')
def test_message(message):
    emit('my response', {'data': message['data']}, broadcast=True)

@socketio.on('connect', namespace='/test')
def test_connect():
    emit('my response', {'data': 'Connected'})

@socketio.on('disconnect', namespace='/test')
def test_disconnect():
    print('Client disconnected')

if __name__ == '__main__':
    socketio.run(app)

SocketIO客户端程序

$(document).ready(function(){
    var socket = io.connect('http://' + document.domain + ':' + location.port + '/test');
    socket.on('my response', function(msg) {
        $('#log').append('<p>Received: ' + msg.data + '</p>');
    });
    $('form#emit').submit(function(event) {
        socket.emit('my event', {data: $('#emit_data').val()});
        return false;
    });
    $('form#broadcast').submit(function(event) {
        socket.emit('my broadcast event', {data: $('#broadcast_data').val()});
        return false;
    });
});
 类似资料: