この間SignalRで云々というエントリを投稿したが、SignalRそのものの説明が無かったので、簡単に説明しておこうかと。
SignalRはasp.net coreアプリとして、HUB(サーバ)を作成することにより、複数のクライアントとHUB間でメッセージのやりとりを行う事ができる仕組み。
クライアント用ライブラリは.net,java,javascriptが用意されている。
クライアントから、HUBに接続し、下記のような事を行う事が可能。
- サーバからのPush配信
- クライアントからHUB経由で全クライアントまたはグループ内クライアントへメッセージ一斉送信
- クライアントからHUB経由で特定のクライアントへメッセージ送信
実装想定例としては、
- サーバからの高頻度の更新を必要とするアプリ、例えばGPSを利用した位置特定および周辺情報のリアルタイム表示
- システム監視アプリ
- チャットなどのコミュニケーションアプリ
- ホワイトボードなどのコラボレーションアプリ
仕組みとしては、クライアント~HUB間の接続を行った後、RPCを用いて、クライアント側からHUBのプロシジャ(実装はメソッド)を実行したり、クライアント側でHUBからのメッセージ受信イベントハンドラ(メッセージ毎に定義可能)を定義して、特定処理を行う。
簡単な例を挙げると、以下のような感じでチャットアプリのようなものを作成することが可能。
HUB側
// HUBに接続されている、全てのクライアントにメッセージ送信
public async Task SendMessageAll(string user, string message) {
await Clients.All.SendAsync("ClientMessge",user,message);
}
// HUB側からのPush通知
private async Task Notify(string message) {
await Clients.All.SendAsync("SystemNotify", message);
}
Client側
HubConnection con = HubConnectionBuilder()
.WithUrl("http://・・・")
.Build();
// メッセージハンドラの登録
con.On<string,string>("ClientMessage",
(user,message) => {
// 処理
}
);
con.On<string>(""SystemNotify",
(message) => {
// 処理
}
);
・・・
// 現在HUBに接続している全てのクライアントにメッセージ送信要求
await con.InvokeAsync("SendMessageAll",MyUserName,Message);
HUB側ではClients.Allの他
- Clients.Other 要求元以外のクライアント
- Clients.Group 特定のグループ
- Clients.User 特定のユーザ
- Clients.AllExcept 指定されたユーザ以外全て
- Clients.Caller 呼出元のクライアント
等、送信先の指定が可能。
クライアント側は
On<パラメータ型,[パラメータ型,…]>(メッセージID,メッセージハンドラ)
の形で複数種類のメッセージをハンドリングする事が可能。
※パラメータの型はHUB上の定義と合っていなければハンドリングされない。
blazor wasm版などと組み合わせると、結構面白いアプリを作成することができるのでは無いだろうか。
ちなみに、クライアント,HUB双方でメソッド名やメッセージ名を文字列で扱っているが、バグの温床となり得るので、Interfaceを作成して、nameof(メソッド名)やnameof(メッセージ名)等とすると良いだろう。
詳細は下記などを参照
https://docs.microsoft.com/ja-jp/aspnet/core/signalr/introduction?view=aspnetcore-3.1
ちなみに、サーバアプリにHUBの登録を行うためには、Startup.csに下記の記述が必要。
ConfigureService
services.AddCors(options => {
options.AddPolicy(<ポリシー名>,
builder => {
builder.Allow・・・
.AllowAnyHeader() // これが無いとクライアントでエラーが発生
});
});
services.AddSignalR(options => {
options.EnableDetailedErrors = true;
});
Configure(“/myhub”)となる(“/HubのロケーションURL”);
app.UseCors(<ポリシー名>);
・・・
app.UseEndpoints(endpoints =>
{
// このWebAppのBase Url + Hubのルーティング先を定義
// Base Urlが/mywebappでHubクラスがMyHub
// http://・・・/mywebapp/myhubをHubの接続先としたい場合、
// endpoints.MapHub
endpoints.MapHub
});