.NETでプッシュ型通信
Silverlight と Windows Azure の組み合わせで何かできないかなぁと思って、この土日はその辺りのことをちらほら調べてた。
WCF / WPF アプリ
Windows のレンタルサーバーに WCF サービスおいて、クライアントも普通の .NET アプリ(Silverlight とかでなく)なら、netTcpBinding とか wsDualHttpBinding の双方向サービスおけば済む話なんですが。
でも、双方向サービスって full-trusted な環境でないと使えないから、Windows Azure ではホストできないのね・・・。(Windows Azure は partial-trusted で動いてるらしい。Azure 側からよそ様にデータ送りつけるってのができない。)
あと、クライアント側も、Xbap は partial-trusted なので無理臭い。
Silverlight その1(Socket 直接利用)
Silverlight だと、basicHttpBinding しか使えなくて困る。
自前サーバー持ってたり専用ホスティングサーバー借りてるなら、Socket を直接使ってプッシュ型通信する方法はあるんですけども。
この方法は自分でも試したみたことあるけども、TcpListener とか触ったことのある人なら割と簡単にできると思う。サーバー側で TcpListener 直接使えるならかなりお勧め。
ちなみに、通常の .NET Framework と Silverlight 版では Socket の仕様が違うので注意(WPF と Silverlight でコード使いまわしたいときとかに)。
Silverlight その2(System.ServiceModel.PollingDuplex.dll)
一応、Silverlight でも双方向通信するためのライブラリはあるみたい。
- 参考
- How to: Access a Duplex Service with the Channel Model | Microsoft Docs
- How to: Build a Duplex Service for a Silverlight Client | Microsoft Docs
- Dan Wahlin - Pushing Data to a Silverlight Client with a WCF Duplex Service - Part I
- Dan Wahlin - Pushing Data to a Silverlight Client with a WCF Duplex Service – Part II
どういうものかというと、
- Silverlight SDK についてきてる
- Silverlight 側から定期的にサーバーにポーリングかけることで双方向通信っぽいこと実現してる
というのなんですけども。
ちょっと頑張ろうとしてみたけども、使うの結構大変そう。
WPF アプリの「Visual Studio のサービス参照機能でひな形コード作ってもらって簡単プログラミング」みたいなノリで使えるかと期待して触ると絶望する。
普通に basicHttpBinding 使って、自前でポーリングの仕組み書く方が楽かもしれないなぁ・・・
おまけ
ActiveWeb 借りてるんですけども、最初 WCF サービスが動かなくて困った。
で、ちょっとググったら解決方向発見: 2008-09-21
ほんと、レンタルサーバー上でのデバッグってどうするのがいいんでしょうねぇ。
ちゃんと調べれば、Parallels Plesk とかのコントロールパネル上から見れるログを残せる気もするんですけども。
とりあえず、面倒だったので、表示したいログメッセージを詰めた例外を投げて、エラー画面を通してログを見ることに。
public override ServiceHostBase CreateServiceHost( string constructorString, Uri[] baseAddresses) { var sb = new System.Text.StringBuilder(); foreach (var a in baseAddresses) { sb.AppendLine(a.AbsoluteUri); } throw new InvalidOperationException(sb.ToString()); }
その結果、ActiveWeb の場合、ufcpp.jp と www.ufcpp.jp の両方を使ってサイトにアクセスできるのがエラーの原因っぽかった。
baseAddresses に http://ufcpp.jp/ServiceName.svc と http://www.ufcpp.jp/ServiceName.svc の2つが渡されるけども、結局この2つって同じアドレスを指すんで、2度同じエンドポイントを作ろうとして失敗するみたい。
なので、やっぱり適当だけど、以下のような方法でエラー回避できそう。
public class HogeServiceHostFactory : ServiceHostFactory { protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) { ServiceHost result = base.CreateServiceHost(serviceType, baseAddresses.Take(1).ToArray(); return result; } }
ほんとは、URI が同じアドレス指してるかどうかを判定して、重複を削除するようなコード書くのが正しい気がする。LINQ を使えば割と簡単に書けそうかも。