跳到主要内容

传输与协商

SignalR 用可插拔的传输在客户端与服务器之间承载帧。aiosignalr 实现了 ASP.NET Core 的三种标准传输。

传输概览

传输全双工服务器 → 客户端客户端 → 服务器二进制(MessagePack)
WebSocketsWebSocket 帧WebSocket 帧
ServerSentEventsSSE 流HTTP POST✘(仅文本)
LongPolling长轮询响应HTTP POST

只有 WebSockets 是真正的全双工;另外两个是半传输,把接收路径与用于发送的 HTTP POST 配对。

协商

客户端每次连接都以:

POST {endpoint}/negotiate[?negotiateVersion=1[&useStatefulReconnect=true]]

开始。服务器回应 connectionIdconnectionTokennegotiateVersionavailableTransports,以及(协商同意时)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"] }
]
}

传输选择

  1. 服务器按偏好顺序列出传输。
  2. 客户端按以下条件过滤:
    • 客户端允许使用的传输集合;
    • 协商的 hub 协议的传输格式兼容性 (MessagePack 需要支持二进制的传输;SSE 仅文本)。
  3. 第一个兼容的传输胜出,客户端连接到 {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"})

相关