ASP.NET Core SignalR Swift 客户端

SignalR Swift 是用于从 Swift 应用程序连接到 SignalR 服务器的客户端库。 本文档概述了如何安装客户端、建立连接、处理服务器到客户端调用、调用服务器方法、处理流式处理响应以及配置自动重新连接和其他选项。

SignalR安装客户端包

SignalR Swift 客户端库以 Swift 包的形式交付。 可以使用 Swift 包管理器将其添加到项目中。

要求

  • Swift >= 5.10
  • macOS >= 11.0
  • iOS >= 14

使用 Swift 包管理器进行安装

在你的 Package.swift 文件中将 SignalR Swift 包添加为依赖项:

// swift-tools-version: 5.10
import PackageDescription

let package = Package(
    name: "signalr-client-app",
    dependencies: [
        .package(url: "https://github.com/dotnet/signalr-client-swift", branch: "main")
    ],
    targets: [
        .executableTarget(name: "YourTargetName", dependencies: [.product(name: "SignalRClient", package: "signalr-client-swift")])
    ]
)

添加依赖项后,在 Swift 代码中导入库:

import SignalRClient

连接到中心

要建立连接,请创建一个 HubConnectionBuilder 并使用 withUrl() 方法为其配置一个 SignalR 服务器 URL。 生成连接后,调用 start() 以连接到服务器:

import SignalRClient

let connection = HubConnectionBuilder()
    .withUrl(url: "https://your-signalr-server")
    .build()

try await connection.start()

从中心调用客户端方法

若要从服务器接收消息,请使用 on 该方法注册处理程序。 on 方法需要 Hub 方法的名称和一个闭包,当服务器调用该方法时,这个闭包将被执行。

以下方法的名称是 ReceiveMessage. 参数名称为usermessage

await connection.on("ReceiveMessage") { (user: String, message: String) in
    print("\(user) says: \(message)")
}

connection.on 中的上述代码在服务器端代码使用 SendAsync 方法调用它时运行:

using Microsoft.AspNetCore.SignalR;
namespace SignalRChat.Hubs;

public class ChatHub : Hub
{
    public async Task SendMessage(string user, string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
}

SignalR通过匹配SendAsyncconnection.on中定义的方法名称和参数,来确定要调用的客户端方法。

最佳做法是在on之后在HubConnection上调用try await connection.start()方法。 这样做可确保在接收任何消息之前注册处理程序。

从客户端调用中心方法

Swift 客户端可以使用 HubConnection 的 invoke 方法或 send 方法在服务器上调用集线器方法。 该方法 invoke 等待服务器的响应,如果调用失败,则引发错误,而 send 该方法不会等待响应。

在以下代码中,中心上的方法名称为 SendMessage。 传递给 invoke 的第二个和第三个参数映射到中心方法的 usermessage 参数:

// Using invoke, which waits for a response
try await connection.invoke(method: "SendMessage", arguments: "myUser", "Hello")

// Using send, which does not wait for a response
try await connection.send(method: "SendMessage", arguments: "myUser", "Hello")

当服务器上的方法返回时,该方法 invoke 返回返回值(如果有)。 如果服务器上的方法引发错误,该函数将引发错误。

伐木业

Swift 客户端库包括专为 Swift 应用程序设计的轻型日志记录系统。 它提供了一种结构化的方式,用于使用可自定义的日志处理程序记录不同严重程度的消息。 在 Apple 平台上,它利用 os.Logger 进行高效的系统日志记录,而在其他平台上,则回退到标准控制台输出。

日志级别

用于 HubConnectionBuilder().withLogLevel(LogLevel:) 设置日志级别。 使用指定的日志级别和更高级别记录消息:

  • LogLevel.debug:可用于调试的详细信息。
  • LogLevel.information:常规应用程序消息。
  • LogLevel.warning:有关潜在问题的警告。
  • LogLevel.error:需要立即注意的错误。

客户端结果

除了调用服务器方法外,服务器还可以在客户端上调用方法并等待响应。 若要支持此功能,请定义一个从其关闭返回结果的客户端处理程序:

await connection.on("ClientResult") { (message: String) in
    return "client response"
}

例如,服务器可以在客户端上调用 ClientResult 该方法并等待返回的值:

public class ChatHub : Hub
{
    public async Task TriggerClientResult()
    {
        var message = await Clients.Client(connectionId).InvokeAsync<string>("ClientResult");
    }
}

处理流式传输响应

若要从服务器接收数据流,请使用 stream 该方法。 该方法返回可以异步循环访问的流:

let streamResult: any StreamResult<String> = try await connection.stream(method: "StreamMethod")
for try await item in streamResult.stream {
    print("Received item: \(item)")
}

处理丢失的连接

自动重新连接

SignalR Swift 客户端支持自动重新连接。 若要启用它,在生成连接时使用AutomaticReconnect()进行调用。 默认情况下禁用自动重新连接。

let connection = HubConnectionBuilder()
    .withUrl(url: "https://your-signalr-server")
    .withAutomaticReconnect()
    .build()

如果没有参数,withAutomaticReconnect() 将客户端配置为在每次重新连接尝试之前分别等待 0、2、10 和 30 秒。 尝试四次失败后,客户端将停止尝试重新连接。

在开始任何重新连接尝试之前,HubConnection 转换为 Reconnecting 状态并触发其 onReconnecting 回调。

重新连接成功后, HubConnection 转换到 connected 状态并触发其 onReconnected 回调。

使用onReconnectingonReconnected的一种常规方法是标记连接状态的变化:

connection.onReconnecting { error in
    // connection is disconnected because of error
}

connection.onReconnected {
    // connection is connected back
}

在自动重新连接中配置策略

若要自定义重新连接行为,可以传递一个数字数组,表示每次重新连接尝试前的延迟(以秒为单位)。 若要进行更精细的控制,请传递符合 RetryPolicy 协议的对象。

使用包含延迟值的数组

let connection = HubConnectionBuilder()
    .withUrl(url: "https://your-signalr-server")
    .withAutomaticReconnect([0, 0, 1]) // Wait 0, 0, and 1 second before each reconnect attempt; stop after 3 attempts.
    .build()

使用自定义重试策略

实现 RetryPolicy 协议来控制重新连接计时:

// Define a custom retry policy
struct CustomRetryPolicy: RetryPolicy {
    func nextRetryInterval(retryContext: RetryContext) -> TimeInterval? {
        // For example, retry every 1 second indefinitely.
        return 1
    }
}

let connection = HubConnectionBuilder()
    .withUrl(url: "https://your-signalr-server")
    .withAutomaticReconnect(CustomRetryPolicy())
    .build()

配置超时和“保持活动状态”选项

可以通过 HubConnectionBuilder 自定义客户端的超时和保持连接设置:

选项 默认值 说明
withKeepAliveInterval 15 (秒) 确定客户端发送 ping 消息的间隔,并直接在 HubConnectionBuilder 上设置。 使用此设置,服务器可以检测强行断开连接的情况,例如客户断开其计算机的网络连接。 从客户端发送任何消息会将计时器重置为间隔的开始。 如果客户端在服务器设置的 ClientTimeoutInterval 内未发送消息,服务器会认为客户端已断开连接。
withServerTimeout 30 (秒) 确定客户端在考虑服务器断开连接之前等待服务器响应的间隔。 此设置直接在 HubConnectionBuilder 上设置。

配置传输

SignalR Swift 客户端支持三种传输:LongPolling、ServerSentEvents 和 WebSocket。 默认情况下,如果服务器支持 WebSocket,客户端将使用 WebSocket,如果服务器不支持,则回退到 ServerSentEvents 和 LongPolling。 可以通过在生成连接时调用 withUrl(url:transport:) 来配置客户端以使用特定传输。

let connection = HubConnectionBuilder()
    .withUrl(url: "https://your-signalr-server", transport: .webSockets) // use websocket only
    .build()
let connection = HubConnectionBuilder()
    .withUrl(url: "https://your-signalr-server", transport: [.webSockets, .serverSentEvents]) // use websockets and server sent events
    .build()

其他资源