Ключевой сущностью в SignalR, через которую клиенты обмениваются сообщеними с сервером и между собой, является хаб (hub). Хаб представляет некоторый класс, который унаследован от абстрактного класса Microsoft.AspNetCore.SignalR.Hub.
Простейший хаб:
using Microsoft.AspNetCore.SignalR; namespace SignalRApp { public class ChatHub : Hub { public async Task Send(string message) { await Clients.All.SendAsync("Receive", message); } } }
Класс хаба может определять различные методы с различными параметрами, однако клиент может обращаться только к публичным методам хаба.
Например, в данном случае определен публичный метод Send
, который принимает параметр типа string. А это значит,
что клиент может вызвать на хабе этот метод и передать ему некоторую строку. Метод может содержать различную логику, но в данном случае
метод просто транслирует полученную строку всех подключенным клиентам.
Для использования функциональности библиотеки SignalR, в приложении надо зарегистрировать соответствующие сервисы с помощью метода AddSignalR():
using SignalRApp; // пространство имен класса ChatHub var builder = WebApplication.CreateBuilder(args); builder.Services.AddSignalR(); // подключаем сервисы SignalR var app = builder.Build(); app.UseDefaultFiles(); app.UseStaticFiles(); app.MapHub<ChatHub>("/chat"); app.Run();
Перегузка этого метода принимает в качестве параметра делегат Action, который имеет параметр типа HubOptions.
ISignalRServerBuilder AddSignalR(); ISignalRServerBuilder AddSignalR(Action<HubOptions> configure);
Параметр configure
позволяет сконфигурировать подключение хаба. В частности, класс HubOptions определяет ряд свойств:
ClientTimeoutInterval. Определяет время, в течение которого клиент должен отправить серверу сообщение. Если в течение данного времени никаких сообщенй от клиента на сервер не пришло, то сервер закрывает соединение.
По умолчанию равно 30 секунд.
HandshakeTimeout. После подключения к серверу клиент должен отправить серверу в качестве самого первого сообщения специальное сообщение - HandshakeRequest. Это свойство устанавливает допустимое время таймаута, которое может пройти до получения от клиента первого сообщения об установки соединения. Если в течение этого периода клиент не отправит первое сообщение, то подключение закрывается.
По умолчанию равно 15 секунд.
KeepAliveInterval: если в течение этого периода сервер не отправит никаких сообшений, то автоматически отправляется ping-сообщение для поддержания подключения открытым. При изменении этого свойства Microsoft рекомендует изменить на стророне клиента параметр serverTimeoutInMilliseconds (клиент javascript)/ ServerTimeout(клиент .NET), которое рекомендуется устанавливать в два раза больше, чем KeepAliveInterval.
По умолчанию равно 15 секунд.
SupportedProtocols определяет поддерживаемые протоколы. По умолчанию поддерживаются все протоколы.
EnableDetailedErrors при значении true возвращает клиенту детальное описание возникшей ошибки (при ее возникновении). Поскольку подобные сообщения могут содержать критически важную для безопасности информацию, то по умолчанию имеет значение false.
StreamBufferCapacity определяет максимальный размер буфера для входящего потока клиента. По умолчанию равно 10.
MaximumReceiveMessageSize определяет максимальный размер для входящего сообщения. По умолчанию - 32 кб
MaximumParallelInvocationsPerClient определяет максимальное количество методов хаба, которые клиент может вызвать параллельно. По умолчанию равно 1.
Мы можем настроить параметры глобально для всех хабов в приложении, либо для хабов отдельного типа. Глобальная настройка хабов:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddSignalR(hubOptions => { hubOptions.EnableDetailedErrors = true; hubOptions.KeepAliveInterval = TimeSpan.FromMinutes(1); });
Настройка только для хаба ChatHub:
var builder = WebApplication.CreateBuilder(args); builder.Services.AddSignalR().AddHubOptions<ChatHub>(options => { options.EnableDetailedErrors = true; options.KeepAliveInterval = System.TimeSpan.FromMinutes(1); });
Можно комбинировать оба вида настроек:
builder.Services .AddSignalR(hubOptions => { hubOptions.EnableDetailedErrors = true; hubOptions.KeepAliveInterval = TimeSpan.FromMinutes(1); }) .AddHubOptions<ChatHub>(options => { options.EnableDetailedErrors = false; options.KeepAliveInterval = TimeSpan.FromMinutes(5); });
При этом настройки для отдельного хаба переопределяют глобальные настройки.
Чтобы сервер мог сопоставить запросы с определенным хабом вызывается метод MapHub():
app.MapHub<ChatHub>("/chat");
С помощью метода MapHub() можно сопоставить URL с хабом. В данном случае все запросы по адресу "/chat" будут обрабатываться хабом ChatHub.
Перегрузка метода MapHub дополнительно принимает делегат с параметром типа HttpConnectionDispatcherOptions, благодаря чему мы можем настроить различные настройки подключения
HubEndpointConventionBuilder MapHub<THub>(string pattern, Action<HttpConnectionDispatcherOptions>? configureOptions) where THub : Hub;
В частности, в HttpConnectionDispatcherOptions есть следующие свойства:
ApplicationMaxBufferSize: максимальный размер буфера в байтах, в который сервер помещает получаемые от клиента данные.
По умолчанию равно 64 килобайта.
AuthorizationData: представляет список (объект IList) объектов IAuthorizeData, которые определяют, авторизован ли клиент для подключения к хабу.
TransportMaxBufferSize максимальный размер буфера в байтах, в который сервер помещает данные для отправки клиенту.
По умолчанию равно 64 килобайта.
MinimumProtocolVersion: минимальная версия протокола. Применяется, чтобы отсеить клиентов определенных версий
Transports представляет битовую маску из значений перечисления HttpTransportType, которая устанавливает допустимые типы транспорта. По умолчанию применяются все типы транспорта
LongPolling представляет объект LongPollingOptions, который настраивает транспорт LongPolling. Этот класс имеет только одно свойство PollTimeout, которое устанавливает периодичность опроса. По умолчанию равно 90 секунд.
WebSockets представляет объект Microsoft.AspNetCore.Http.Connections.WebSocketOptions, который настраивает транспорт WebSocket. У данного объекта можно установить два свойства:
CloseTimeout
: временный интервал после закрытия сервера, в течение которого клиент должен
закрыть подключение. Если клиенту не удастся закрыть подключение, то соединение с сервером автоматически завершается.
SubProtocolSelector
: делегат, который устанавливает заголовок Sec-WebSocket-Protocol.
Применим некоторые свойства:
using Microsoft.AspNetCore.Http.Connections; // пространство имен перечисления HttpTransportType using SignalRApp; // пространство имен класса ChatHub var builder = WebApplication.CreateBuilder(args); builder.Services.AddSignalR(); var app = builder.Build(); app.UseDefaultFiles(); app.UseStaticFiles(); app.MapHub<ChatHub>("/chat", options => { options.ApplicationMaxBufferSize = 128; options.TransportMaxBufferSize = 128; options.LongPolling.PollTimeout = TimeSpan.FromMinutes(1); options.Transports = HttpTransportType.LongPolling | HttpTransportType.WebSockets; }); app.Run();