跳到主要内容

客户端、分组与用户

服务器通过 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_idctx.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)。开启状态化重连后, 编码字节还会喂给每个接收者的消息缓冲,因此发送时断线的客户端重连后也能收到。