重温WCF之数单向通讯、双向通讯、回调操作(五)

时间:2023-12-11 16:16:14

一.单向通讯
单向操作不等同于异步操作,单向操作只是在发出调用的瞬间阻塞客户端,但如果发出多个单向调用,WCF会将请求调用放入到服务器端的队列中,并在某个时间进行执行。队列的存储个数有限,一旦发出的调用个数超出了队列容量,则会发生阻塞现象,此时调用请求无法放入队列,直到有其他请求被处理。
WCF中所有的绑定都支持单向通讯。
二.双向通讯
WCF请求-应答模式是WCF中默认的操作模式。应答的默认超时时间为1分钟,如果超过一分钟没有应答,客户端就会获得一个TimeOutException异常。WCF中除了NetPeerTcpBinding和NetMsmqBinding绑定,所有的绑定都支持请求-应答操作。
三.回调操作
WCF回调操作简单的说就是由服务器端来调用客户端的方法,回调时原先的服务端和客户端将发生对调,服务端成为客户端,客户端成为服务端。
WCF回调的必要条件:
并不是所有的绑定都支持回调操作,只有具有双向通讯能力的绑定才可以使用回调。比如HTTP是与连接无关的,因此不能用于回调。这就是说明我们不能使用BasicHttpBinding或WSHttpBinding进行回调。WCF中NetTcpBinding和NetNamedPipeBinding支持回调,因为从本质上讲TCP和IPC协议支持双向通信。WCF中wsDualHttpBinding也是支持回调的,因为它实际上是设置了两个HTTP通道,一个用于从客户端到服务的调用,另一个用于服务到客户端的调用。
回调操作时通过回调契约来实现的,回调契约属于服务契约的一部分,一个服务契约最多只能包含一个回调契约。一旦定义了回调契约,就需要客户端实现回调契约。在WCF中,可以通过ServiceContract的CallbackContract属性来定义回调契约。

以下是代码实现:

1.启用单向通讯的方法,不能有返回值(void可以),不能有out参数,只允许传入参数。

    [ServiceContract(Namespace = "MyNamespace")]
public interface IService
{
[OperationContract(IsOneWay = true)]
void DoTestWork(string message);
}

2.双向通讯是有问必有答的(哪怕方法返回void,客户端也会收到一条空消息)。

    [ServiceContract(Namespace = "MyNamespace")]
public interface IService
{
[OperationContract(IsOneWay = false)]
DateTime DoTestWork(string message);
}

 3.回调操作代码实现


WCF服务端

 // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”。
[ServiceContract(Namespace="http://yxlblogs.cnblogs.com/WCF/Callback",CallbackContract=typeof(ICallback))]
public interface IService1
{ [OperationContract(IsOneWay = true)]
void Add(int a,int b); } // 回调契约的定义,此时回调契约不需要应用ServiceContractAttribute特性
public interface ICallback
{
[OperationContract(IsOneWay=true)]
void ShowResult(int a ,int b);
} // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“Service1”。
// 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 Service1.svc 或 Service1.svc.cs,然后开始调试。
public class Service1 : IService1
{
public void Add(int a, int b)
{
a++;
b++;
ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>();
// 对客户端操作进行回调
callback.ShowResult(a, b);
}
}

Web配置文件:

<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="WcfService1.Service1">
<endpoint address="" binding="wsDualHttpBinding" contract="WcfService1.IService1"/>
</service>
</services>
</system.serviceModel>

客户端调用:

 class Program
{
private static void Main(string[] args)
{
InstanceContext instanceContext = new InstanceContext(new CallbackService());
Service1Client client = new Service1Client(instanceContext); client.Add(, );
Console.ReadKey(); }
} // 客户端中对回调契约的实现
public class CallbackService : IService1Callback//生成的接口名为服务契约+Callback
{
public void ShowResult(int a, int b)
{
Console.WriteLine(a+b);//结果为5
}
}