前回では、バインディングにNetNamedPipeBindingを利用していましたが
今回は、メッセージキュー(NetMsmqBinding)を利用してみます。
メッセージキューを利用するバインディングですので
当然ながら、MSMQが動作していないと動きません。
Windows Server 2008 R2などの場合は、サーバーマネージャから
「機能の追加」でインストールできます。
NetMsmqBindingは、文字通りMSMQ (メッセージキュー)をトランスポートとして
利用するバインディングです。このバインディングは他のバインディングとは
ちょっと違う点があります。
今までのバインディングの場合、クライアントとサーバーが直接
やり取りをしていましたが、MSMQバインディングを利用する場合、
クライアントとサーバーの間にメッセージキューが仲介として入ります。
イメージとしては以下のような感じ。
クライアント ⇔ MSMQ ⇔ サービスホスト
クライアントから送信したデータは、メッセージキューにenqueueされ
サービスホストは、メッセージキューからデータをdequeueします。
なので、NetMsmqBindingを利用している場合、クライアントは
MSMQが動いていれば、サービスホストが起動していなくても動きます。
(メッセージキューにデータがたまっていきます。)
で、サービスホストは起動したらメッセージキューに溜まっている
データを取得し、処理が流れていきます。
メッセージキューを利用する場合は、以下の組み合わせを利用します。
- バインディングはNetMsmqBindingを利用
- アドレスのスキームはnet.msmqを指定
NetMsmqBindingを利用する場合、アドレスはキューの場所を示すように設定します。
(例)net.msmq://localhost/private/testqueue
以下、サンプルです。
まずサービス定義.
using System; using System.Collections.Generic; using System.Linq; using System.ServiceModel; namespace Gsf.Samples.WCF { [ServiceContract(Namespace="http://Gsf.Samples.WCF")] public interface IMyService { [OperationContract(IsOneWay=true)] void SendData(int value); } }
using System; using System.Collections.Generic; using System.Linq; namespace Gsf.Samples.WCF { public class MyService : IMyService { public void SendData(int value) { Console.WriteLine("[CALL] SendData() : {0}", value); } } }
次にホストアプリ。
ホストアプリでは、最初にメッセージキューに利用するキュー名が存在するか
どうかを確認しています。無ければ作成しておきます。
尚、メッセージキューを操作する場合は、System.Messagingの参照設定が必要です。
using System; using System.Collections.Generic; using System.Linq; using System.Messaging; using System.ServiceModel; namespace Gsf.Samples.WCF { class Program { const string TX_QUEUE_NAME = @".\private$\testqueue"; static void Main(string[] args) { // // キューにサンプルで利用する名前が存在するか確認. // なければ、ここで作成しておく. // if (!MessageQueue.Exists(TX_QUEUE_NAME)) { MessageQueue.Create(TX_QUEUE_NAME, true); } using (var host = new ServiceHost(typeof(MyService))) { host.Open(); Console.WriteLine("サービスが開始されました。"); Console.WriteLine("press <ENTER> to exit..."); Console.ReadLine(); host.Close(); } } } }
ホスト側のアプリケーション構成ファイル。
アドレスの部分にて、メッセージキュー(NetMsmqBinding)を指定しています。
尚、私の環境ではActive Directory統合を無効化した状態でインストールしていますので
bindingの設定にてsecurityモードをNoneに設定しています。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <services> <service name="Gsf.Samples.WCF.MyService"> <host> <baseAddresses> <add baseAddress="net.msmq://localhost/private/testqueue"/> </baseAddresses> </host> <endpoint address="" binding="netMsmqBinding" contract="Gsf.Samples.WCF.IMyService" bindingConfiguration="NoMsmqSecurity" /> </service> </services> <bindings> <netMsmqBinding> <binding name="NoMsmqSecurity"> <security mode="None" /> </binding> </netMsmqBinding> </bindings> </system.serviceModel> </configuration>
次にクライアント側。
using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace Gsf.Samples.WCF { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void btnCallServiceMethod_Click(object sender, EventArgs e) { using (var client = new MyServiceRef.MyServiceClient()) { var rnd = new Random(); client.SendData(rnd.Next()); client.Close(); } } } }
最後にクライアント側のアプリケーション構成ファイル。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.serviceModel> <client> <endpoint address="net.msmq://localhost/private/testqueue" binding="netMsmqBinding" contract="MyServiceRef.IMyService" bindingConfiguration="NoMsmqSecurity"/> </client> <bindings> <netMsmqBinding> <binding name="NoMsmqSecurity"> <security mode="None" /> </binding> </netMsmqBinding> </bindings> </system.serviceModel> </configuration>
クライアント側からサービスメソッドを呼び出すといつも通り動きます。
その後、ホストアプリ側だけを落として、クライアントの「サービス呼び出し」
ボタンを何回かクリックします。ホスト側は落ちているのに正常に動作します。
メッセージキューを見てみると、ホストアプリを落としてから、クライアントが
送ったデータがキューに残っているのがわかります。
クライアントを落として、今度はホストアプリのみを起動すると
先ほどキューに溜まっていたデータが処理されます。
サンプルは以下の場所にアップしてあります。
https://sites.google.com/site/gsfzero1/Home/WCF-Sample-005.zip?attredirects=0&d=1
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ