SignalRというテクノロジを試してみたんだけど、これすごい便利。

というのも、従来、(HTTP限定ね)クライアントとサーバー間でデータのやりとりをしようと思うと、自分でクライアントとサーバー間の調停を行うコードを双方に記述しなければならなかった。なぜなら関数呼び出しみたいに処理結果が返ってきたり、イベントが返ってきたりはしないから。どうやっていたかというと

1. (C)データ投げる -> (S)受け取る
2. (C)しばらく待つ XX (S)処理し管理
3. (C)データ頂戴 -> (S)管理データを返す

と面倒なうえ、そもそも、"しばらく待つ"というのも時間が決まっていないし、データの処理が終わったとしてもイベントドリブンで結果をサーバからクライアントに返せない。

しかも、1対1ならまだしもデータのやり取りは複数スレッド発生するのがほとんどで、自分が投げたデータはすべてにIDを割り振りったりが必要だし、クライアントが勝手に死んだ場合の処理データはいつまでサーバで保持するのかとか、ひじょーに面倒。

#ちなみに、ASP.NET(完全C#)を使った個人的な世界で1つのプロキシを作ってます
#なんでかって?だって80ポートのHTTPしか通過できないのよ(TT)
#それに世に知られたアプリには頼れないんだよね。

で、SignalRだとどうなるか。

1. (C)データ投げる -> (S)受け取り処理し管理 -> (C)管理データが返される

と1ステップで完了します。しかも非同期、同期どちらも簡単に実現できる。

今のところ、簡単なサンプルしかなくて、SignalR版プロキシというかトンネルソフトを実現するためには色々試行錯誤が必要だった。しかもクライアントは大抵JS向けでC#クライアントはあんまりない。ので参考に記載しておく。

○クライアント側

プロジェクトは普通に空のC# GUIアプリ(でもなんでもOK)作る。SignalR関連の参照は登録しておく。

接続処理は、Main()関数でいきなりサーバに繋げておく。Onの処理はまだ書かないでOK。
また、起動時1回だけ接続すればOK。データのやり取りするたびに接続が必要だと思っていたけど無駄。

HubConnection = new HubConnection("http://192.168.1.xxx/HogeServer");
ServerHubProxy = HubConnection.CreateHubProxy("ServerHub");
HubConnection.Start().Wait();

で、サーバーのAPI呼び出しはこんな感じで、戻り値が必要ならawait使えばいいし、不要ならWait()つかってもいい。

int ret = await ServerHubProxy.Invoke("ConnectToHttpServer",...);

ServerHubProxy.Invoke("SendData").Wait();

#サーバからイベントを受け取りたい場合は、MSDNのサンプルみたいにOnを使えばいい。
#最初はOnを使ってイベントで受け取っていたけど、単純なデータであればOnは不要だと分かったので取っ払った
##なお、Onの登録は処理が発生するたびに何度行ってもたぶん問題なさそうな感じだった

あとデータのIDを管理するのにContextのContextIdは使えない。データ単位で作られる訳ではなくクライアント単位なので、どのデータも同じIDになってしまう。なので自前でGuid.NewGuid()とかで作る。


○サーバ側

サーバーは最初Azureでないとだめかと思ったけど、IIS(8.5?)でOKだった。プロジェクトを発行する際は、Azureがデフォだったりするけど、普通にIISサーバのwwwroot以下にサイトを作ってそこにファイルコピー(VSで"Webサイトの発行...")をすればよい。あとは勝手にVSやIISがやってくれる。

プロジェクトは普通のASP.NET WEBサイトを作ればOK。

クライアントが呼び出すメソッドも普通に作っておけばよい。引数や戻り値の型は従来通りプリミティブなものでないと厳しいはずなので、適宜文字列にシリアライズするなど必要。


あと、一般的なASP.NETでのサーバの実装の注意だけど

・クラスのメンバ変数は保持されないはずなので、static変数などで管理するのを忘れずに。
・クライアントの要請でサーバ側が作ったIDisposableなオブジェクトの破棄のクライアントからの依頼も当然忘れずに


以上