Flask-Socketio 部分翻译

翻译 2017年01月03日 12:30:15

待验证

  1. server端emit数据到浏览器,浏览器端收到数据,无法触发emit指定的回调函数。

广播 Broadcasting

以下 socketio 为 SocketIO的一个实例

Broadcast是SocketIO中非常实用的特性,在 send()emit() 中指定 broadcast = True 可以激活这个特性:

@socketio.on('my event')
def handle_my_custom_event(data):
    emit('my response', data, broadcast=True)

当一条消息通过broadcast的方式发送出去时,当前命名空间内的所有连接都会接收到这条消息,包括触发上述代码中 ‘my event’ 事件的连接。若没有使用命名空间,属于默认命名空间的所有连接都会收到消息。注意, broadcast 消息是不会触发回调函数的
上述代码是通过某个连接触发事件后,调用包含该连接上下文的emit函数来发送广播消息的,但某些情况下,服务器应该成为这个广播消息的发送者。
socketio.send() 以及 socketio.emit() 方法可以将消息广播给所有连接。

def some_function():
    socketio.emit('some event', {'data': 42})

值得注意的是,与 sned(),emit() 这两个函数相比, socketio.send(),socketio.emit() 不需要客户端连接的上下文,所以 broadcast = True 是被默认设置的。


房间 Rooms

对于一些应用来说,需要将用户分为不同的组来进行管理。比如聊天室应用,一个用户可以属于多个组,要获取所属的一个或多个组的聊天信息。Flask-SocketIO通过两个函数 join_room 和 leave_room 实现这种分组的概念。

from flask_socketio import join_room, leave_room

@socketio.on('join')
def on_join(data):
    username = data['username']
    room = data['room']
    join_room(room)
    send(username + ' has entered the room.', room=room)

@socketio.on('leave')
def on_leave(data):
    username = data['username']
    room = data['room']
    leave_room(room)
    send(username + ' has left the room.', room=room)

send() 和 emit() 函数接受一个名为 room 的参数,发送消息时指定此参数,可以将消息发送给’存在’在该房间的所有用户。
任何用户(连接)一旦连接成功,都被分配了一个room,该room以 request.sid 命名。一个用户可以加入任何名字的任何room(即不限于已存在的rooms)。当一个用户disconnect后,所有(这个用户加入过的)房间都会移除这个用户的信息。
无需上下文的 socketio.send() 和 socketio.emit() 也接受一个room参数,将消息发送给该room中所有用户。
既然每个用户都属于一个房间,如果想要给某个用户发消息,只要将room参数指定为此用户的 request.sid 即可


连接事件(Connection Events)

Flask-SocketIO 允许在客户端连接以及断开时触发用户自定义事件:

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

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

如果 connect 事件返回 False,那么此连接将失败,因此可以在这里进行用户认证操作。
值得注意的是,连接事件以及断开连接事件在不同的命名空间有不同的表现。


基于类的命名空间

除了使用装饰器指定回调,还可以使用类来定义同一命名空间的各种事件:

from flask_socketio import Namespace, emit

class MyCustomNamespace(Namespace):
    def on_connect(self):
        pass

    def on_disconnect(self):
        pass

    def on_my_event(self, data):
        emit('my_response', data)

socketio.on_namespace(MyCustomNamespace('/test'))

As a convenience to methods defined in a class-based namespace, the namespace instance includes versions of several of the methods in the flask_socketio.SocketIO class that default to the proper namespace when the namespace argument is not given.

使用这种方式处理事件的话,服务端接收到事件后,会映射到以 on_ 开头的同名函数,比如浏览器传来的是 my_event, 那么服务端调用的即 on_my_event 函数; 如果没有对应的处理函数,事件就会被忽略。(注意函数名不允许出现非法字符)
如果基于类的处理方法和基于装饰器的方法同时存在,则仅有基于装饰器的方法会被调用。


使用Flask的上下文

SocketIO事件的处理函数和flask的路由处理函数有明显的区别,在SocketIO事件处理程序中,什么能做什么不能做往往容易引起一些困惑。主要区别在于,一个客户端连接产生的所有SocketIO相关事件,都会发生在一个单独的长期存在的连接中。
尽管存在这些区别,Flask-SocketIO依旧希望SocketIO事件的运行环境与普通的HTTP连接请求尽可能的相似,以简化SocketIO事件的处理方式。以下将陈述一些最佳实践:
1. 应用上下文往往是在事件请求触发之前被推入栈,以便于在处理函数中使用 current_appg 变量。
2. 请求上下文往往也是在请求触发之前被推入栈,以便于在处理函数中使用 requestsession 变量。但是,Websocket触发的事件是不会引起单独的请求的,所以上述情况不会在此时发生。因此,引发Websocket连接的请求的请求上下文将在此连接的整个生命周期存在,被所有触发的事件使用。
3. request 这个全局变量将拥有额外的变量 sid,此变量的值是每个连接独一无二的session ID。这个值也被用作每个客户端连接的初始房间号。
4. request 这个全局变量将拥有额外的变量 namespaceevent ,值是当前处理的命名空间和所触发的事件的参数。 event 变量类型为字典,拥有 messageargs 的key。
5. session 这个全局变量在SocketIO中的表现与在普通的HTTP请求中的表现是不同的。在SocketIO连接建立后,一份用户session的拷贝能够被该连接上下文触发的事件处理函数所使用。如果SocketIO注册的处理函数修改了此session变量,这个被修改过的session会被保存,并能够被将来触发的回调函数使用,与此同时,普通的HTTP请求处理函数不会察觉到这个变化。Effectively, when a SocketIO handler modifies the session, a “fork” of the session is created exclusively for these handlers. The technical reason for this limitation is that to save the user session a cookie needs to be sent to the client, and that requires HTTP request and response, which do not exist in a SocketIO connection. When using server-side sessions such as those provided by the Flask-Session or Flask-KVSession extensions, changes made to the session in HTTP route handlers can be seen by SocketIO handlers, as long as the session is not modified in the SocketIO handlers.
6. before_requestafter_request 的钩子对于SocketIO的事件是无效的。
7. SocketIO的处理函数可以使用自定义的装饰器,但是大多数Flask的装饰器往往不适合SocketIO处理函数,因为在SocketIO连接中不存在Response对象的概念。


认证

获取用户身份是一个应用的常见需求,传统的基于表单和HTTP请求的机制在SocketIO连接中显然不再适用,因为根本没有用到HTTP请求和HTTP响应的地方。如果真的有这个必要,应用可以通过SocketIO的message方式,在页面点击提交后发送自定义的登陆表单到服务端进行验证。
但是多数情况下,建立SocketIO连接之前,使用传统的认证方式相对而言似乎更加方便。用户的身份可以被记录在 session或是cookie中,在SocketIO连接建立后那些信息也将被SocketIO的处理函数所使用。

相关文章推荐

在flask中使用WebSocket

原文:Easy WebSockets with Flask and Gevent 但是还没有翻译完,后面会进行更新的 我很高兴地介绍Flask-SocketIO,这是一个非常易于使用的扩展,可以...

Gevent-socketio文档-Socket.IO的一个python实现

原文链接 https://gevent-socketio.readthedocs.org/en/latest/ 简介 Gevent-socketio的目的之一是实现一个可以运行在各种基于WSGI的w...

socket.io emit的几种用法解释

// send to current request socket client socket.emit('message', "this is a test"); // sending to al...

Flask Socketio前后端通信问题

最近在用socketio进行前后端通信时遇到一个问题:前端可以向后台发送数据,但是后台却无法把数据发送到前端。 前端采用socketio 后台使用falsk-socketio...

js锁定web页面到浏览器

原来不能说是锁定,只是弹出的

【hadoop】三种模式的区别

Hadoop can be run in 3 different modes. Different modes of Hadoop areStandalone Mode Default mode of...

Flask-babel简单实例(修正原文部分错误版)

转载自:http://blog.csdn.net/lichengtongxiazai/article/details/22270561  这位老兄也是修正了原文的部分错误。但是他也犯了个小错误,我只好...

Flask 教程,第二部分:模板

概述 如果你已经阅读过上一个章节,那么你应该已经完成了充分的准备工作并且创建了一个很简单的具有如下文件结构的Web应用: 01 microblog ...
  • qfatao
  • qfatao
  • 2014年01月20日 14:25
  • 3261

flaskWeb开发(基于python的web开发实战)-第一部分-Flask简介

### 第二章 程序的基本结构 ``` from flask import Flask from flask import request # 程序上下文包括current_app, g, 请求上...

Flask 教程,第三部分:Web 表单

概要 在前面章节我们为主页定义了一个简单的模板,部分尚未实现的模块如用户或帖子等使用模拟的对象作为临时占位。 本章我们将看到如何利用web表单填补这些空白。 web表单是web应用中...
  • qfatao
  • qfatao
  • 2014年01月23日 09:43
  • 13861
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Flask-Socketio 部分翻译
举报原因:
原因补充:

(最多只允许输入30个字)