传输与协商
SignalR 用可插拔的传输在客户端与服务器之间承载帧。aiosignalr 实现了 ASP.NET Core 的三种标准传输。
传输概览
| 传输 | 全双工 | 服务器 → 客户端 | 客户端 → 服务器 | 二进制(MessagePack) |
|---|---|---|---|---|
WebSockets | ✔ | WebSocket 帧 | WebSocket 帧 | ✔ |
ServerSentEvents | ✘ | SSE 流 | HTTP POST | ✘(仅文本) |
LongPolling | ✘ | 长轮询响应 | HTTP POST | ✔ |
只有 WebSockets 是真正的全双工;另外两个是半传输,把接收路径与用于发送的 HTTP POST 配对。
协商
客户端每次连接都以:
POST {endpoint}/negotiate[?negotiateVersion=1[&useStatefulReconnect=true]]
开始。服务器回应 connectionId、connectionToken、negotiateVersion、
availableTransports,以及(协商同意时)useStatefulReconnect: true。
{
"connectionToken": "05265228-...",
"connectionId": "807809a5-...",
"negotiateVersion": 1,
"useStatefulReconnect": true,
"availableTransports": [
{ "transport": "WebSockets", "transferFormats": ["Text", "Binary"] },
{ "transport": "ServerSentEvents", "transferFormats": ["Text"] },
{ "transport": "LongPolling", "transferFormats": ["Text", "Binary"] }
]
}
传输选择
- 服务器按偏好顺序列出传输。
- 客户端按以下条件过滤:
- 客户端允许使用的传输集合;
- 协商的 hub 协议的传输格式兼容性 (MessagePack 需要支持二进制的传输;SSE 仅文本)。
- 第一个兼容的传输胜出,客户端连接到
{endpoint}?id={connectionToken}。
WebSocket
connection = HubConnection() # 默认优先尝试 WebSocket
await connection.start("ws://host:8080/hub")
- 文本帧携带 JSON 协议消息;二进制帧携带 MessagePack。
- 客户端在升级请求上附带 HTTP 请求头(
Authorization: Bearer ...、自定义头)。 - 只有 WebSocket 传输支持状态化重连。
Server-Sent Events
服务器 → 客户端的事件以 SSE data: 块到达(仅 JSON);客户端通过 HTTP POST
发往同一 ?id= URL。
await connection.start(url, transports={"ServerSentEvents"})
Long Polling
客户端发出 GET,服务器持有直到有帧可投递(或超时);发送用 HTTP POST。
await connection.start(url, transports={"LongPolling"})
传输格式
协商好的 hub 协议决定传输必须支持的传输格式:
- JSON →
Text - MessagePack →
Binary
对 WebSocket,传输格式还决定帧类型(文本 vs 二进制)。aiosignalr 无论使用 哪种传输,都按当前协议编码每一帧。
强制指定传输
# 只允许列出的传输
await connection.start(url, transports={"WebSockets", "LongPolling"})