python-socketio 文档翻译
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python-socketio 文档翻译相关的知识,希望对你有一定的参考价值。
参考技术A教程: https://tutorialedge.net/python/python-socket-io-tutorial/
python-socketio 原文地址 ,在google浏览器中可以翻译为中文去使用。
首先要搞明白几个问题:
说明
1)第一种room是每一个单独的客户端都有的。(通过 session ID 可以找到)
2)第二种是应用程序自己创建的。
在下面这个方法中,如果省略掉room参数,将会自动发送给所有的连接了的客户端。
译文:
Python-socketio实现了一个Python Socket.IO 服务,这个服务可以单独运行也可以综合于一个web项目中。下面是一些它的特征:
什么是Socket.IO?
Socket.IO是一个基于事件的双向通讯的传输协议(一般是web浏览器),和一个服务端。原始的客户端和服务端组件实现是通过javascript写的。
入门指南
可以使用 pip 安装Socket.IO:
下面是一个使用 aiohttp 框架(只支持Python 3.5+)实现异步IO的 Socket.IO server 简单的例子:
下面是一个类似的例子,但是使用的Flask和Eventlet的例子,兼容Python2.7和3.3+:
客户端应用必须引入 socket.io-client 库(1.3.5版本以及以上,越高越好)。
每次客户端连接到服务器的连接事件处理程序调用sid(会话ID)分配给连接和WSGI环境字典。
每次客户端连接到服务端的 conenct 事件都是由sid(session ID)分配到连接和WSGI环境字典调用的。服务端可以检查身份认证或者其他的头部信息去决定是否这个客户端允许被连接。要想拒绝一个客户端的连接,这个处理器必须返回 False 。
当客户端发送发送一个事件给服务端,相应的事件处理器会被 sid 和这个信息调用,可以是单个或者多个参数。这个应用可以定义尽量多的如果被需要的可以被事件处理器关联的事件。一个事件可以通过一个名称简单定义。
当一个客户端连接中断了, disconnect 事件就被调用,允许应用去执行清理工作。
服务端
Socket.IO 服务端是 socketio.Server 类的实例,他们可以被一个WSGI适用应用程序使用 socketio.Middleware 去合并:
使用 socketio.Server.on() 方法来注册服务端的事件处理器:
对于异步服务端来说,事件处理器可以是常规方法,或者是协程:
聊天室
因为Socket.IO是一个双向的协议,服务端可以在任意时间发送消息给任意的连接到的客户端。为了让它方便去将客户端定位到组中,应用程序可以将客户端放入到聊天室中去,然后将消息定位到整个聊天室中。
当客户端第一次连接,他们是被分配到他们自己的聊天室中,这个聊天是是以session ID(sid 参数会传递给所有的事件处理器)命名的。应用可以通过 socketio.Server.enter_room() 和 socketio.Server.leave_room() 自由地去创建聊天室和管理客户端。客户端可以在尽量多的房间里,也可以根据需求尽量频繁地被拉入拉出聊天室。当他们的连接不在特别的时候,单独的聊天室将会分配给她它们,应用程序可以自由地增加和移除客户端从聊天室中,尽管它只要这样做就会失去定位独立客户端的能力。
socketio.Server.emit() 方法会获得一个事件名称,一个可能是 str , bytes , list , dict 或者 tuple 类型的消息载体。当发送一个 tuple ,在其中的元素必须是上面的其他类型。元组中的元素将会被传递给客户端的回调函数为多个参数。定位一个个人客户端,客户端的 sid 将会被给一个聊天室(假设这个应用没有修改这些初始的聊天室)。定位所有的连接的客户端们,这个聊天室参数将会被触发。
通常在聊天室中当广播一个消息到一个用户组的时候,发送者是否接受他自己的消息是可选的。 soicketio.Server.emit() 方法提供了一个可选的 skip_sid 参数去指定一个想在广播中跳过的客户端。
Response
当一个客户端发送一个事件给服务端,它可以选择提供一个回调方法,当服务端返回一个响应的时候会被触发。服务端可以便捷地从相应的事件处理器返回它从而提供一个响应。
事件处理器可以返回一个单独的值,一个带多个值的元组。这个在客户端的回调函数将会调用这些返回的值。
Callbacks
回调
服务端可以请求一个响应通过发送一个事件给客户端。 socketio.Server.emit() 方法有一个可选的 callback 参数能够被设置为可回调的。当这个参数被传递之后,当客户端返回相应的时候,这个可回调的方法将会被请求。
当广播给多个客户端的时候使用回调函数是不被推荐的,因为回调方法将会被只执行一次。
Namespace
命名空间
Socket.IO 协议支持多个逻辑性连接,所有的多路复用都是在相同的物理连接上。客户端可以通过给每个连接指定不同的 namespace 从而开多个连接。一个命名空间是由 主机名+端口+路径名称构成的。比如,连接到 http://example.com:8000/chat 将会开一个连接到命名空间 /chat 。
由于分离的不同的session ID( sid s),不同的事件处理器,不同的聊天室,每一个命名空间都是独立的。应用程序使用多个命名空间从而来区分命名空间,是非常重要的。可以参考 socketio.Server 类。
当 namespace 参数被触发了,比如设置为 None 或者 / , 那么一个默认的命名空间将会被使用。
Class-Based Namespaces
作为一个基于装饰器的事件处理器的代替,这个属于一个命名空间事件处理器可以被创建为 socketio.Namesapce 的子类:
对于基于异步io的服务端,域名空间必须继承与 socketio.AsyncNamespace , 也可以定义普通的方法或者协程作为事件处理器:
当使用基于类的命名空间的时候,任何被服务端接受的事件将会被分派到一个被事件名称命名的方法中作为方法名称(with the on_pfrefix )。比如:事件 my_event 将会被一个名叫 on_my_event 的方法处理。
让频道与 Python-socketio 中的房间一致,以及一般的 pubsub 问题
【中文标题】让频道与 Python-socketio 中的房间一致,以及一般的 pubsub 问题【英文标题】:Have channels coincide with rooms in Python-socketio, and general pubsub questions 【发布时间】:2021-11-10 22:56:50 【问题描述】:我正在使用 python-socketio 处理一个涉及 websockets 的项目。 我们主要关心的是流动性,每个连接的用户都会有一个光标,其在板上的位置每 50 毫秒作为事件发送一次,板被标识为(套接字)房间,我们期待其中的许多。
我是 PubSub 的新手,我们正在横向扩展我们的架构,它似乎适合事件广播。
我查看了 AsyncRedisManager 类,据我了解,似乎 any 消息,由 any socketio 上的 any 套接字发送服务器(带有 pub/sub)然后通过 single 通信通道从该服务器传输/发布到 redis。然后,此频道的订阅者可以看到此消息流。
因此我担心三件事:
由于所有消息都只是通过一个通道,这不是“设计缺陷”吗,因为某些服务器可能没有连接到“一个”特定房间的套接字(目前),但它们仍然会接收(并且 pickle .loading),他们当时并不关心的消息。 这些消息的实际详细信息(房间、有效负载等)由服务器pickled.dumped 和pickle.loaded。如果有 50 个房间,每个房间有 50 个游标,每个房间发送 25 个事件/秒,这会不会是一个巨大的 CPU 限制瓶颈? 我正在研究 socket.io 文档,将 redis 适配器与 Python-socketio pubsub 管理器并排比较,似乎通道是动态命名空间的,如“socketio#room_name”和广播到这些“命名空间”的消息” 频道,因此 psubscribe 将是一个可行的解决方案。其他一些 MQ 以“主题”的形式引用。 如果前一个假设是正确的,我们仍然不能假设一台服务器是否应该订阅频道#room_name,除非房间中没有或至少有一个用于该服务器的套接字。我理解 pub/sub 的范式是,来自 Redis 页面:
相反,发布的消息被描述为频道,而不知道可能有哪些订阅者(如果有的话)。订阅者对一个或多个频道表示兴趣,并且只接收感兴趣的消息,而不知道有哪些(如果有)发布者。
但我的问题可以概括为: 是否可以让 Python-socketio 服务器在需要时动态订阅/取消订阅频道,将频道标识为房间,因此总共有与房间一样多的频道。在将这种“即插即用”的简单逻辑保留为 pubsubManager 子类的同时,这是否可行?我是否遗漏了什么或者这有意义吗?
感谢您的宝贵时间,任何想法、更正或“草稿”代码将不胜感激。
【问题讨论】:
【参考方案1】:是否可以让 Python-socketio 服务器在需要时动态订阅/取消订阅频道,并将频道标识为房间
我想这是可能的,使用自定义客户端管理器类。您需要从现有的客户端管理器或基本客户端管理器之一继承,并实现适合您需要的不同发布/订阅逻辑。但请记住,如果您有 10,000 个客户,那么至少会有 10,000 个房间,因为每个客户都有一个私人房间。
【讨论】:
嘿@Miguel!感谢您的回答,您的意见对我来说非常宝贵。很抱歉非常坚持,但是我以前对您的代码的假设是否正确?只是想确定我明白了。另外,在那种情况下,我想我需要在同一个客户端管理器中创建许多 self.pubs / self.subs,因为我认为不可能在 socketio.AsyncServer 的构造函数中“附加”许多 client_managers ?最后,关于何时计划迁移到 aioredis2 支持的任何愿景?愿意贡献。谢谢! 如果你问我是否同意当前的方法是一个“设计缺陷”,那么不,我不同意。但如果这种类型的解决方案更适合您的需求,那么正如我在回答中所说,您完全可以实现自己的发布/订阅机制。以上是关于python-socketio 文档翻译的主要内容,如果未能解决你的问题,请参考以下文章