Wcf(,service callback client)
大家好,这段时间又研究了一下wcf的通信,一般都是client call service,service响应,返回信息给client,这个时候需要用到的binding(如wsHttpBinding,basicHttpBinding).
但是有时候,可能逻辑都写在服务端,然后界面写在客户端,控制界面的逻辑都是由服务端控制的,这就需要由服务端去callback客户端,这时候就需要用到binding(WSDualHttpBinding,NetTcpBinding)
在WCF预定义绑定类型中,WSDualHttpBinding和NetTcpBinding均提供了对双工通信的支持,但是两者在对双工通信的实现机制上却有本质的区别。WSDualHttpBinding是基于HTTP传输协议的;而HTTP协议本身是基于请求-回复的传输协议,基于HTTP的通道本质上都是单向的。WSDualHttpBinding实际上创建了两个通道,一个用于客户端向服务端的通信,而另一个则用于服务端到客户端的通信,从而间接地提供了双工通信的实现。而NetTcpBinding完全基于支持双工通信的TCP协议。
下面就是一个简单地列子:客户端调用服务端,服务端计算后,回调客户端显示。
第一步:定义服务契约和回调契约:
[ServiceContract(CallbackContract = typeof(ICalculatorCallback))] public interface ICalculator { [OperationContract(IsOneWay = true)] void Add(double x, double y); } public interface ICalculatorCallback { [OperationContract(IsOneWay = true)] void DisplayResult(double x, double y, double result); }
其中发现在回调契约这可以不用定义[ServiceContract]
第二部:实现服务
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)] public class CalculatorService : ICalculator { public void Add(double x, double y) { double result = x + y; ICalculatorCallback callback = OperationContext.Current.GetCallbackChannel<ICalculatorCallback>(); callback.DisplayResult(x, y, result); } }
第三部:配置文件
<system.serviceModel> <behaviors> <serviceBehaviors> <behavior name="calculatorServieBehavior"> <serviceMetadata httpGetEnabled="true"/> </behavior> </serviceBehaviors> </behaviors> <services> <service name="Platform.Service.CalculatorService" behaviorConfiguration="calculatorServieBehavior"> <endpoint address="" binding="wsDualHttpBinding" contract="Platform.Contract.ICalculator" name="wsDualHttpBinding"/> <endpoint address="" binding="netTcpBinding" contract="Platform.Contract.ICalculator" name="netTcpBinding"/> <host> <baseAddresses> <add baseAddress="http://127.0.0.1:9888/CalculatorService"/> <add baseAddress="net.tcp://127.0.0.1:9999//CalculatorService"/> </baseAddresses> </host> </service> </services> </system.serviceModel>
第四部:启动服务
using (ServiceHost calculatorSerivceHost = new ServiceHost(typeof(CalculatorService))) { calculatorSerivceHost.Opened += delegate { Console.WriteLine("Calculator Service has begun to listen ... ..."); }; calculatorSerivceHost.Open(); Console.Read(); }
第五步:客户端调用,在客户端选择add service reference,添加CalculatorService服务,生成代理
代理主要包括两个接口服务接口和回调接口
第六步:客户端代码,继承实现服务端回调接口
public class CalculateCallback : ICalculatorCallback { public void DisplayResult(double x, double y, double result) { Console.WriteLine("x + y = {2} when x = {0} and y = {1}", x, y, result); } }
第七部:实现客户端调用代理
InstanceContext instanceContext = new InstanceContext(new CalculateCallback()); using (DuplexChannelFactory<ICalculator> channelFactory = new DuplexChannelFactory<ICalculator>(instanceContext, "wsDualHttpBinding")) { ICalculator proxy = channelFactory.CreateChannel(); using (proxy as IDisposable) { proxy.Add(1, 2); Console.Read(); } }