SignalR 入門

投稿者: Patrick Fletcher

警告

このドキュメントは、最新版の SignalR を対象としていません。 ASP.NET Core SignalR に関する記事を参照してください。

この記事では、SignalR の概要と SignalR で作成されるソリューションの一部について説明します。

質問とコメント

このチュートリアルの感想、改善に関するフィードバックをページの下部にあるコメント欄にお寄せください。 チュートリアルに直接関連しない質問がある場合は、ASP.NET SignalR フォーラムまたは StackOverflow.com に投稿できます。

SignalR とは

ASP.NET SignalR は、ASP.NET 開発者向けのライブラリです。リアルタイム Web 機能をアプリケーションに追加するプロセスを簡略化できます。 リアルタイム Web 機能とは、クライアントから新しいデータが要求されるのをサーバーに待機させるのではなく、コンテンツが使用可能になったらすぐに、サーバー コードから接続クライアントに対してコンテンツをプッシュする機能です。

SignalR を使用すると、ASP.NET アプリケーションにあらゆる種類の "リアルタイム" Web 機能を追加できます。 チャットは一例としてよく使用されますが、さらに多くのことを行うことができます。 ユーザーが Web ページを更新して新しいデータを表示するたびに、またはそのページで長いポーリングを実装して新しいデータを取得するたびに、SignalR を使用する機会が発生します。 たとえば、ダッシュボードと監視アプリケーション、共同作業アプリケーション (ドキュメントの同時編集など)、ジョブの進行状況の更新、リアルタイム フォームなどがあります。

SignalR では、リアルタイム ゲームなど、サーバーからの高頻度の更新を必要とするまったく新しい種類のアプリケーションも使用できます。

SignalR には、サーバーからクライアント方向のリモート プロジェクト コール (RPC) を作成するための簡易な API が用意されており、サーバー側の .NET コードからクライアント ブラウザー (および他のクライアント プラットフォーム) を呼び出すことができます。 また、SignalR には、接続管理 (たとえば、接続イベントと切断イベント) の API、接続のグループ化も含まれています。

Invoking methods with SignalR

SignalR では、自動的に接続管理が処理され、ユーザーは、チャットルームのように、同時に接続されているすべてのクライアントにメッセージをブロードキャストすることができます。 また、特定のクライアントにメッセージを送信することもできます。 クライアントとサーバー間の接続は、通信ごとに再確立される従来の HTTP 接続とは異なり、永続的なものです。

SignalR は、"サーバー プッシュ" 機能をサポートしています。これにより、サーバーでは、現在 Web 上では一般的な要求 - 応答モデルではなく、リモート プロシージャ コール (RPC) を使用して、クライアント コードを呼び出すことができます。

SignalR アプリケーションでは、組み込みのサードパーティのスケールアウト プロバイダーを使用して、何千ものクライアントにスケールアウトできます。

組み込みプロバイダーには次のものがあります。

サード パーティ プロバイダーには次のものがあります。

SignalR はオープンソースであり、GitHub からアクセスできます。

SignalR と WebSocket

SignalR は、使用可能な場合は新しい WebSocket トランスポートを使用して、必要に応じて古いトランスポートにフォールバックされます。 WebSocket を直接使用してアプリを作成することもできますが、SignalR を使用するということは、実装に必要なその他の機能の多くが実行されることにもなります。 最も重要なのは、古いクライアント用に別のコード パスを作成するのに気をもむことなく、WebSocket を利用するようにアプリをコーディングできるという点です。 また、SignalR は、基になるトランスポートの変更をサポートするように SignalR が更新されるため、WebSocket の更新について気をもむ必要がなく、WebSocket のバージョン間で一貫したインターフェイスがアプリケーションに提供されます。

トランスポートとフォールバック

SignalR は、クライアントとサーバーの間でリアルタイムの作業を行うために必要なトランスポートの一部を抽象化したものです。 SignalR は、可能な場合に、まず WebSocket 接続を確立しようとします。 WebSocket が SignalR の最適なトランスポートであるのは、次のような点を備えているからです。

  • サーバー メモリの使用が最も効率的。
  • 待機時間が最短。
  • クライアントとサーバーの間の全二重通信など、非常に基になる機能。
  • 非常に厳しい要件として、WebSocket には次のようなサーバーが必要です。
    • Windows Server 2012 または Windows 8 で実行されている。
    • .NET Framework 4.5。

これらの要件が満たされていない場合、SignalR は、他のトランスポートを使用して接続しようとします。

HTML 5 トランスポート

これらのトランスポートは、HTML 5 のサポートに依存します。 クライアント ブラウザーが HTML 5 標準をサポートしていない場合は、古いトランスポートが使用されます。

  • WebSocket (サーバーとブラウザーの両方が Websocket をサポート可能であることを示している場合)。 WebSocket は、クライアントとサーバーの間で真に永続的な双方向接続を確立する唯一のトランスポートです。 ただし、WebSocket には非常に厳しい要件もあります。これは、Microsoft Internet エクスプローラー、Google Chrome、Mozilla Firefox の最新バージョンでのみ完全にサポートされており、Opera や Safari などの他のブラウザーでは、部分的にのみ実装されています。
  • サーバー送信イベント。EventSource とも呼ばれます (ブラウザーがサーバー送信イベントをサポートしている場合は、基本的にインターネット エクスプローラーを除くすべてのブラウザー)。

Comet トランスポート

次のトランスポートは、Comet Web アプリケーション モデルに基づいています。長時間保持された HTTP 要求が、ブラウザーまたはその他のクライアントによって維持されます。サーバーでは、クライアントから特に要求されなくてもクライアントに対してデータがプッシュされるようにこれを使用できます。

  • Forever Frame (Internet Explorer のみ)。 Forever Frame を使用すると、完了していないサーバー上のエンドポイントに要求を行う非表示の IFrame が作成されます。 その後、サーバーでは、スクリプトがクライアントに継続的に送信されます。この操作はすぐに実行され、サーバーからクライアントへの一方向のリアルタイム接続が行われます。 クライアントからサーバーへの接続では、サーバーからクライアントへの接続とは別の接続を使用します。標準の HTTP 要求と同様に、送信する必要があるデータごとに新しい接続が作成されます。
  • Ajax の長いポーリング。 長いポーリングによって永続的な接続が作成されることはありませんが、サーバーが応答するまで開いたままの要求を使用して、サーバーがポーリングされます。この時点で、接続は閉じ、新しい接続がすぐに要求されます。 これにより、接続のリセット中に待機時間が発生する可能性があります。

どの構成でどのトランスポートがサポートされているかに関する詳細については、「サポートされているプラットフォーム」を参照してください。

トランスポート選択プロセス

次の一覧は、使用するトランスポートを決めるために SignalR で使用される手順を示しています。

  1. ブラウザーが Internet Explorer 8 以前の場合は、長いポーリングが使用されます。

  2. JSONP が構成されている (つまり、接続開始時に jsonp パラメータが true に設定される) 場合は、長いポーリングが使用されます。

  3. クロス ドメイン接続が確立されている場合 (つまり、SignalR エンドポイントがホスティング ページと同じドメインにはない場合)、次の条件が満たされている場合に WebSocket が使用されます。

    • クライアントが CORS (クロス オリジン リソース共有) をサポートしている。 CORS をサポートしているクライアントの詳細については、caniuse.com で CORS を参照してください。

    • クライアントが WebSocket をサポートしている

    • サーバーが WebSocket をサポートしている

      これらの条件のいずれかが満たされていない場合は、長いポーリングが使用されます。 クロスドメイン接続の詳細については、「クロスドメイン接続を確立する方法」を参照してください。

  4. JSONP が構成されておらず、接続がクロス ドメインではない場合、WebSocket は、クライアントとサーバーの両方によってサポートされている場合に使用されます。

  5. クライアントまたはサーバーのいずれかが WebSocket をサポートしていない場合、サーバーイベントが使用可能であれば使用されます。

  6. サーバー送信イベントが使用できない場合は、Forever Frame が試行されます。

  7. Forever Frame が失敗した場合は、長いポーリングが使用されます。

トランスポートの監視

アプリケーションで使用されているトランスポートを判断するには、ハブ上でのログ記録を有効にするか、ブラウザーでコンソール ウィンドウを開きます。

ブラウザーでハブのイベントのログ記録を有効にするには、クライアント アプリケーションに次のコマンドを追加します。

$.connection.hub.logging = true;

  • Internet Explorer で、F12 キーを押して開発者ツールを開き、[コンソール] タブをクリックします。

    Console in Microsoft Internet Explorer

  • Chrome で、Ctrl + Shift + J キーを押してコンソールを開きます。

    Console in Google Chrome

コンソールを開いてログ記録を有効にすると、SignalR で使用されているトランスポートを確認できます。

Console in Internet Explorer showing WebSocket transport

トランスポートの指定

トランスポートのネゴシエートには、一定の時間がかかり、クライアントやサーバーのリソースが必要となります。 クライアント機能がわかっている場合は、クライアント接続の開始時にトランスポートを指定できます。 次のコード スニペットは、クライアントが他のプロトコルをサポートしていないことがわかっていた場合に使用されるように、Ajax Long Polling トランスポートを使用して接続を開始する方法を示しています。

connection.start({ transport: 'longPolling' });

クライアントで特定のトランスポートを順に試す場合は、フォールバックの順序を指定できます。 次のコード スニペットは、WebSocket の試行と失敗、長いポーリングへの直接の移動を示しています。

connection.start({ transport: ['webSockets','longPolling'] });

トランスポートを指定するための文字列定数は、次のように定義されます。

  • webSockets
  • foreverFrame
  • serverSentEvents
  • longPolling

接続とハブ

SignalR API には、クライアントとサーバーの間で通信するための 2 つのモデル (永続的な接続とハブ) が用意されています。

接続は、単一受信者のメッセージ、グループ化されたメッセージ、またはブロードキャスト メッセージを送信するための単純なエンドポイントを表します。 永続的な接続 API (PersistentConnection クラスによって .NET コードで表されます) を使用すると、SignalR で公開されている低レベルの通信プロトコルに開発者が直接アクセスできるようになります。 接続通信モデルの使用は、Windows Communication Foundation などの接続ベースの API を使用したことがある開発者にとっては親しみやすい方法となるでしょう。

ハブは、クライアントとサーバーがメソッドを直接呼び出しあうことをできる接続 API に基づいて構築されたより高レベルのパイプラインです。 SignalR では、マジックのようにマシン境界を越えたディスパッチが処理されます。これにより、クライアントでは、ローカル メソッドと同じくらい簡単に、サーバー上のメソッドを呼び出すことも、その逆を行うこともできます。 Hub 通信モデルの使用は、.NET リモート処理などのリモート呼び出し API を使用したことがある開発者にとっては親しみやすい方法となるでしょう。 ハブを使用すると、厳密に型指定されたパラメータをメソッドに渡して、モデル バインドを有効にすることもできます。

アーキテクチャの図

次の図は、ハブ、永続的な接続、トランスポートに使用される基になるテクノロジの関係を示しています。

SignalR Architecture Diagram showing APIs, transports, and clients

ハブのしくみ

サーバー側のコードがクライアントでメソッドを呼び出すと、呼び出されるメソッドの名前とパラメータを含むアクティブなトランスポート全体でパケットが送信されます (オブジェクトがメソッド パラメータとして送信されると、JSON を使用してシリアル化されます)。 その後、クライアントでは、メソッド名と、クライアント側コードで定義されているメソッドとの一致が行われます。 一致する場合は、逆シリアル化されたパラメータ データを使用して、クライアント メソッドが実行されます。

メソッド呼び出しは、Fiddler などのツールを使用して監視できます。次の図は、Fiddler の [ログ] ウィンドウで SignalR サーバーから Web ブラウザー クライアントに送信されるメソッド呼び出しを示しています。 メソッド呼び出しは MoveShapeHub という名前のハブから送信されます。呼び出されているメソッドは updateShape という名前です。

View of Fiddler log showing SignalR traffic

この例では、ハブ名は H パラメータで識別されます。メソッド名は、M パラメータで識別されます。メソッドに送信されたデータは、A パラメータで識別されます。 このメッセージを生成したアプリケーションは、高頻度リアルタイムのチュートリアルで作成します。

通信モデルの選択

ほとんどのアプリケーションでは、ハブ API を使用する必要があります。 接続 API は、次の状況で使用できます。

  • 送信される実際のメッセージの形式を指定する必要がある。
  • 開発者は、リモート呼び出しモデルではなく、メッセージングおよびディスパッチ モデルを使用することを好みます。
  • メッセージング モデルが使用されている既存のアプリケーションは、SignalR を使用するように移植されています。