WCF 第四章 绑定 netMsmqBinding

MSMQ 为使用队列创建分布式应用程序提供支持。WCF支持将MSMQ队列作为netMsmqBinding绑定的底层传输协议的通信。 netMsmqBinding绑定允许客户端直接把消息提交到一个队列中同时服务端从队列中读取消息。客户端和服务端之间没有直接通信过程;因此,通信本 质是断开的。也意外着所有的通信必须是单向的。因此,所有的操作必须要在操作契约上设置IsOneWay=true属性。

提示 动态创建队列

使用netMsmqBinding时动态创建MSMQ队列是很普通的。当创建一个离线客户端应用而且队列在一个用户的桌面时使用netMsmqBinding绑定更加平常。这可以通过创建System.MessageQueue类的静态方法来实现。

下面的代码显示了netMsmqBinding绑定的地址格式:

  net.msmq:{hostname}/[private/|[public/]]{query name}

  MSMQ默认端口是1801而且没有配置解决方案。注意地址格式中的public和private.你可以显式的确定是否队列名字指向一个私有的或者公有的队列。默认情况下,队列名字假设指向一个公共队列。

表4.11 netMsmqBinding 绑定属性

 

  我们在列表4.2到4.4使用的StockQuoteService样例程序需要被修改以便于与netMsmqBinding绑定一起工作。 netMsmqBinding绑定仅支持单向操作(查看表4.2).我们之前的操作契约使用一个请求回复消息交换模式(查看列表4.4).我们将修改 StockQuoteService例子来显示基于netMsmqBinding绑定的双向通信而不是显示一个不同的例子。

  我们需要使用两个单向操作契约来维护服务端和客户端的双向通信。这意味着我们需要重新定义我们的契约以便于使用netMsmqBinding绑 定。列表4.24显示了写来与netMsmqBinding绑定一起使用的stock quote 契约。首先,注意我们把请求和回复契约转换成两个独立的服务契约:IStockQuoteRequest和IStockQuoteResponse.每个 契约上的操作都是单向的。IStockQuoteRequest契约将被客户端用来向服务端发送消息。IStockQuoteResponse契约将被服 务端用来发送一条消息给客户端。这意味着客户端和服务端都将寄宿服务来接收消息。

列表 4.24 IStockQuoteRequest,IStockQuoteResponse和StockQuoteRequestService

01using System;
02using System.Collections.Generic;
03using System.Linq;
04using System.Text;
05using System.ServiceModel;
06using System.Transactions;
07 
08namespace EssentialWCF
09{
10    [ServiceContract]
11    public interface IStockQuoteRequest
12    {
13        [OperationContract(IsOneWay=true)]
14        void SendQuoteRequest(string symbol);
15    }
16 
17    [ServiceContract]
18    public interface IStockQuoteResponse
19    {
20        [OperationContract(IsOneWay = true)]
21        void SendQuoteResponse(string symbol, double price);
22    }
23 
24    public class StockQuoteRequestService : IStockQuoteRequest
25    {
26        public void SendQuoteRequest(string symbol)
27        {
28            double value;
29            if (symbol == "MSFT")
30                value = 31.15;
31            else if (symbol == "YHOO")
32                value = 28.10;
33            else if (symbol == "GOOG")
34                value = 450.75;
35            else
36                value = double.NaN;
37 
38            //Send response back to client over separate queue
39            NetMsmqBinding msmqResponseBinding = new NetMsmqBinding();
40            using (ChannelFactory<IStockQuoteResponse> cf = new ChannelFactory<IStockQuoteResponse>("NetMsmqResponseClient"))
41            {
42                IStockQuoteResponse client = cf.CreateChannel();
43                using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
44                {
45                    client.SendQuoteResponse(symbol, value);
46                    scope.Complete();
47                }
48                cf.Close();
49            }
50        }
51    }
52}

   netMsmqBinding下一个要考虑的就是使用ServiceHost类。先前的例子可以在不同的绑定上重用相同的ServiceHost代码。这 因为服务契约可以保持一样。而不是因为使用了netMsmqBinding。更新的用来寄宿StockServiceRequestService服务的 ServiceHost代码在列表4.25中显示。我们已经更新代码来动态创建一个在基于配置文件中queueName的MSMQ队列。这有助于通过简单 配置允许程序部署而不需要额外的MSMQ配置。

列表 4.25 StockQuoteRequestService ServiceHost 服务

01using System;
02using System.Collections.Generic;
03using System.Linq;
04using System.Text;
05using System.ServiceModel;
06using System.Configuration;
07using System.Messaging;
08 
09namespace EssentialWCF
10{
11    class Program
12    {
13        static void Main(string[] args)
14        {
15            MyServiceHost.StartService();
16            Console.WriteLine("Service is Started, press Enter to terminate.");
17            Console.ReadLine();
18            MyServiceHost.StopService();
19        }
20    }
21 
22    internal class MyServiceHost
23    {
24        internal static string queryName = string.Empty;
25        internal static ServiceHost myServiceHost = null;
26 
27        internal static void StartService()
28        {
29            queryName = ConfigurationManager.AppSettings["queueName"];
30            if (!MessageQueue.Exists(queryName))
31                MessageQueue.Create(queryName, true);
32            myServiceHost = new ServiceHost(typeof(EssentialWCF.StockQuoteRequestService));
33            myServiceHost.Open();
34        }
35        internal static void StopService()
36        {
37            if (myServiceHost.State != CommunicationState.Closed)
38                myServiceHost.Close();
39        }
40    }
41}

   列表4.26的配置信息使用netMsmqBinding绑定暴露StockQuoteRequestService服务。它也为IStockQuoteResponse契约配置一个客户端终结点以便于回复可以发送给客户端。

列表 4.26 netMsmqBinding 宿主 配置

01<?xml version="1.0" encoding="utf-8" ?>
02<configuration>
03    <system.serviceModel>
04        <client>
05            <endpoint address="net.msmq://localhost/private/stockquoteresponse"
06                binding="netMsmqBinding" bindingConfiguration="NoMsmqSecurity"
07                contract="EssentialWCF.IStockQuoteResponse" name="NetMsmqResponseClient" />
08        </client>
09        <bindings>
10            <netMsmqBinding>
11                <binding name="NoMsmqSecurity">
12                    <security mode="None" />
13                </binding>
14            </netMsmqBinding>
15        </bindings>
16        <services>
17            <service name="EssentialWCF.StockQuoteRequestService">
18                <endpoint address="net.msmq://localhost/private/stockquoterequest"
19                    binding="netMsmqBinding" bindingConfiguration="NoMsmqSecurity"
20                    name="" contract="EssentialWCF.IStockQuoteRequest" />
21            </service>
22        </services>
23    </system.serviceModel>
24  <appSettings>
25    <add key="queueName" value=".\private$\stockquoterequest"/>
26  </appSettings>
27</configuration>

  客户端应用程序必须使用netMsmqBinding寄宿一个服务来接受回复且配置一个终结点来发送请求给服务端。列表4.27 显示了客户端用来寄宿一个实现了IStockQuoteResponse契约的ServiceHost类。我们添加代码来动态创建一个客户端监听的队列。 再次,这有助于通过简单配置允许程序部署而不需要额外的MSMQ配置。

列表 4.27 StockQuoteResponseService ServiceHost 客户端

01using System;
02using System.Collections.Generic;
03using System.Linq;
04using System.Text;
05using System.ServiceModel;
06using System.Configuration;
07using System.Messaging;
08 
09namespace EssentialWCF
10{
11    internal class MyServiceHost
12    {
13        internal static ServiceHost myServiceHost = null;
14 
15        internal static void StartService()
16        {
17            string queryName = ConfigurationManager.AppSettings["queueName"];
18            if (!MessageQueue.Exists(queryName))
19                MessageQueue.Create(queryName, true);
20            myServiceHost = new ServiceHost(typeof(EssentialWCF.Program));
21            myServiceHost.Open();
22        }
23        internal static void StopService()
24        {
25            if (myServiceHost.State != CommunicationState.Closed)
26                myServiceHost.Close();
27        }
28    }
29}

   列表4.28 显示了IStockQuoteResponse接口的客户端实现。客户端实现了接口,接下来被服务端当作发送回复的回调端。这不是使用了WCF中的双向能力。相反的,回调使用一个单独的单向绑定实现。

01using System;
02using System.Collections.Generic;
03using System.Linq;
04using System.Text;
05using System.Threading;
06using System.ServiceModel;
07using System.Transactions;
08 
09namespace EssentialWCF
10{
11    public class Program : IStockQuoteResponse
12    {
13        private static AutoResetEvent waitForResponse;
14        static void Main(string[] args)
15        {
16            //Start response service host
17            MyServiceHost.StartService();
18            try
19            {
20                waitForResponse = new AutoResetEvent(false);
21                //Send request to the server
22                using (ChannelFactory<IStockQuoteRequest> cf = new ChannelFactory<IStockQuoteRequest>("NetMsmqRequestClient"))
23                {
24                    IStockQuoteRequest client = cf.CreateChannel();
25                    using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required))
26                    {
27                        client.SendQuoteRequest("MSFT");
28                        scope.Complete();
29                    }
30                    cf.Close();
31                }
32                waitForResponse.WaitOne();
33            }
34            finally
35            {
36                MyServiceHost.StopService();
37            }
38            Console.ReadLine();
39        }
40 
41        public void SendQuoteResponse(string symbol, double price)
42        {
43            Console.WriteLine("{0}@${1}", symbol, price);
44            waitForResponse.Set();
45        }
46    }
47}

   让netMsmqBinding Stock Quote 样例工作起来的最后一步是客户端配置文件。列表4.29 显示了客户端配置,包含了寄宿IStockQuoteResponse服务实现的信息,调用IStockQuoteRequest服务的终结点配置。

列表 4.29 netMsmqBinding 客户端配置

01<?xml version="1.0" encoding="utf-8" ?>
02<configuration>
03    <system.serviceModel>
04        <bindings>
05            <netMsmqBinding>
06                <binding name="NoMsmqSecurity">
07                    <security mode="None" />
08                </binding>
09            </netMsmqBinding>
10        </bindings>
11        <client>
12            <endpoint address="net.msmq://localhost/private/stockquoterequest"
13                binding="netMsmqBinding" bindingConfiguration="NoMsmqSecurity"
14                contract="EssentialWCF.IStockQuoteRequest" name="NetMsmqRequestClient" />
15        </client>
16        <services>
17            <service name="EssentialWCF.StockQuoteRequestService">
18                <endpoint address="net.msmq://localhost/private/stockquoteresponse"
19                    binding="netMsmqBinding" bindingConfiguration="NoMsmqSecurity"
20                    contract="EssentialWCF.IStockQuoteResponse" />
21            </service>
22        </services>
23    </system.serviceModel>
24  <appSettings>
25    <add key="queueName" value=".\private$\stockquoteresponse"/>
26  </appSettings>
27</configuration>


===========

转载自

 

posted @ 2011-06-29 10:26  Gavin Liu  阅读(220)  评论(0编辑  收藏  举报

Right people get the right information at the right time.
以技术求生存,以市场求发展;学以至用,开拓创新;达技术之颠峰,至市场之广阔!