大家好,这段时间又研究了一下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();
}
}