客户端、分组与用户
服务器通过 self.clients 向客户端发消息,通过 self.groups 管理分组。
发送给所有人
class BroadcastHub(Hub):
async def notify_all(self, text: str) -> None:
await self.clients.all_.send("broadcast", text)
clients.all_ 面向每个已连接客户端,可排除部分连接:
await self.clients.all_.send("broadcast", text, excluded=frozenset({connection_id}))
clients.others 是“除调用者外的所有人”的简写:
await self.clients.others.send("broadcast", text)
发送给指定客户端
# 单条连接
await self.clients.connection(connection_id).send("target", *args)
# 多条连接
await self.clients.connections((id_a, id_b)).send("target", *args)
发送给分组
分组是 hub 管理的命名连接集合:
class RoomHub(Hub):
async def join_room(self, room: str) -> None:
await self.groups.add(room)
async def leave_room(self, room: str) -> None:
await self.groups.remove(room)
async def room_chat(self, room: str, text: str) -> None:
await self.clients.group(room).send("chat", text)
groups.add(name)/groups.remove(name)修改调用者的成员关系。clients.group(name).send(...)向分组广播。- 连接断开时自动移除成员关系。
发送给用户
如果连接带用户 id,可以按用户定位:
await self.clients.user(user_id).send("target", *args)
await self.clients.users((uid_a, uid_b)).send("target", *args)
user_id 从 ctx.context.user_id 读取。默认生命周期管理器按该值匹配。
发送目标一览
| 代理 | 目标 |
|---|---|
all_ | 所有已连接客户端 |
others | 除调用者外的所有客户端 |
connection(id) | 单条连接 |
connections(ids) | 多条连接 |
group(name) | 分组内成员 |
groups(names) | 多个分组成员 |
user(id) | 带指定用户 id 的连接 |
users(ids) | 带指定多个用户 id 的连接 |
每个代理返回一个客户端句柄,提供 send(method, *args)。
广播编码
为提升效率,clients.all_.send(...) 每条协议只序列化一次,并把编码字节
复用到每个接收连接(见 DefaultHubLifetimeManager._send)。开启状态化重连后,
编码字节还会喂给每个接收者的消息缓冲,因此发送时断线的客户端重连后也能收到。