Поделиться через


Клиент Swift для ASP.NET Core SignalR

SignalR Swift — это клиентская библиотека для подключения к серверам SignalR из приложений Swift. В этом документе представлен обзор установки клиента, установления подключения, обработки вызовов между клиентами, вызова серверных методов, работы с ответами потоковой передачи и настройки автоматического повторного подключения и других параметров.

Установка пакета клиента SignalR

Клиентская библиотека Swift SignalR поставляется в виде пакета Swift. Его можно добавить в проект, используя Swift Package Manager.

Требования

  • Swift >= 5,10
  • macOS >= 11.0
  • iOS >= 14

Установка с помощью диспетчера пакетов Swift

Добавьте пакет Swift SignalR в качестве зависимости в файле Package.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 и настройте его с URL-адресом сервера SignalR с помощью метода withUrl(). После создания подключения вызовите start() для подключения к серверу:

import SignalRClient

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

try await connection.start()

Вызов клиентских методов из хаба

Чтобы получить сообщения от сервера, зарегистрируйте обработчик с помощью метода on. Метод on принимает в качестве аргумента имя метода концентратора и замыкание, которое будет выполняться при вызове этого метода сервером.

В следующем тексте имя метода - ReceiveMessage. Имена аргументов user и message:

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 определяет, какой метод клиента следует вызывать путем сопоставления имени метода и аргументов, определенных в SendAsync и connection.on.

Лучшей практикой является вызвать метод try await connection.start() на HubConnection после on. Это гарантирует регистрацию обработчиков перед получением сообщений.

Методы концентратора вызовов от клиента

Клиенты Swift могут вызывать методы концентратора на сервере с помощью invoke или send методов HubConnection. Метод invoke ожидает ответа сервера и выдает ошибку, если вызов завершается сбоем, в то время как метод send не ожидает ответа.

В следующем коде имя метода на хабе SendMessage. Второй и третий аргументы, передаваемые в invoke, соответствуют аргументам user и message метода концентратора.

// 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)")
}

Обработка потерянного соединения

Автоматическое повторное подключение

Клиент Swift SignalR поддерживает автоматическое повторное подключение. Чтобы включить его, вызовите withAutomaticReconnect() при создании подключения. Автоматическое повторное подключение по умолчанию отключено.

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

Без параметров с помощью AutomaticReconnect() клиент настраивается ждать 0, 2, 10 и 30 секунд соответственно перед каждой попыткой повторного подключения. После четырех неудачных попыток клиент перестает выполнять повторное подключение.

Перед началом любых попыток повторного подключения HubConnection переходит в состояние Reconnecting и запускает обратные вызовы onReconnecting.

После успешного повторного подключения HubConnection переходит в состояние connected и запускает обратные вызовы onReconnected.

Общий способ использования onReconnecting и onReconnected заключается в том, чтобы пометить изменения состояния подключения:

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 на сервере, сервер считает, что клиент отключен.
с таймаутом сервера 30 (секунды) Определяет интервал, с которым клиент ожидает ответа от сервера, прежде чем он считает сервер отключенным. Этот параметр устанавливается непосредственно в HubConnectionBuilder.

Настройка транспорта

Клиент SignalR Swift поддерживает три транспорта: LongPolling, ServerSentEvents и WebSockets. По умолчанию клиент будет использовать WebSockets, если сервер поддерживает его, и вернуться к 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()

Дополнительные ресурсы