心海巨澜

天行键,君子以自强不息;地势坤,君子以厚德载物!

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

      单向(One-Way)操作没有返回值,客户端也不会关心调用成功与否,是一种即发即弃的调用方式,通过使用OperationContractAttribute将操作标记为One-Way,在WSDL描述中只包括<input>消息,服务端抛出的任何异常,都不会传递给客户端。理想状态下,一旦客户端调用了一个单向方法,它只会在分发调用的一瞬间被阻塞。但实事上,单向调用并不等同于异步调用。当单向调用到达服务端时,不会立即分发这些调用,而是可能放入到服务端的队列中,并在某个时间被分发。这一过程与服务配置的并发模式行为、队列中的最大消息个数、配置的通道以及可靠性有关。如果队列消息数量超过了队列容量,应会阻塞客户端。然而,一旦调用被放入队列,就会取消对客户端的阻塞。所有的WCF绑定都支持单向操作。

      虽然服务端抛出的任何异常,都不会传递给客户端,然而,在分发一个单向操作时,因为通信问题(例如地址错误或宿主不可用)导致在分发调用时出现的错误,在试图调用操作时,会在客户端抛出一个异常。

      在单调服务中,如果没有传输会话,当调用一个单向操作时,如果发生异常,客户端并不会受到影响,继续发出对相同代理实例的调用。但是如果使用具有安全性的WSHttpBinding绑定,或者使用不包含可靠性消息传输的NetTcpBinding和NetNamedPipeBinding绑定,那么一个服务端的异常,包括单向操作抛出的异常,就会导致通道错误,此时,客户端不能发出任何一个使用相同代理实例的新的调用,客户端甚至不能安全的关闭代理。在使用可靠消息传输的WSHttpBinding绑定或者NetTcpBinding时,异常不会导致通道错误,此时,客户端能够继续发出调用。

      单向操作应用的场景主要为:Fire-and-forget,不需要报告成功与否的操作,如:日志活动或事件发布;Polling,客户端通过一个请求来获得长时间运行的操作的结果;Duplex,One-Way操作特别适用于当涉及到回调操作时的双向通讯。

      下面,我们通过一个DEMO来介绍单向操作:

      主要代码如下:

契约接口代码:

[ServiceContract(Namespace = "http://schemas.xinhaijulan.com/demos/OneWay")]
public interface IMyContract
{
[OperationContract(IsOneWay
= true)]
void MethodWithError();

[OperationContract]
void MethodWithoutError();
}

 

 

实现类代码:

public class MyContract : IMyContract
{
public void MethodWithError()
{
Console.WriteLine(
"Execute MethodWithError");
throw new Exception();
}

public void MethodWithoutError()
{
Console.WriteLine(
"Execute MethodWithoutError");
}
}

 

 

服务端代码:

static void Main(string[] args)
{
StartBasicHttpBindingServer();
//StartNetTcpBindingServer();
}

private static void StartBasicHttpBindingServer()
{
using (ServiceHost host = new ServiceHost(typeof(ServiceLibrary.MyContract)))
{
host.AddServiceEndpoint(
typeof(ServiceLibrary.IMyContract), new BasicHttpBinding(), "http://localhost:8001/MyContract");
host.Open();
Console.WriteLine(
"Please input exit to close host.");
string key = Console.ReadLine();
while (key.ToLower() != "exit")
{
Console.WriteLine(
"Please input exit to close host.");
key
= Console.ReadLine();
}
}
}

private static void StartNetTcpBindingServer()
{
using (ServiceHost host = new ServiceHost(typeof(ServiceLibrary.MyContract)))
{
host.AddServiceEndpoint(
typeof(ServiceLibrary.IMyContract), new NetTcpBinding(), "net.tcp://localhost:9001/MyContract");
host.Open();
Console.WriteLine(
"Please input exit to close host.");
string key = Console.ReadLine();
while (key.ToLower() != "exit")
{
Console.WriteLine(
"Please input exit to close host.");
key
= Console.ReadLine();
}
}
}

 

 

客户端代码:

static void Main(string[] args)
{
TestBasicHttpBinding();
//TestNetTcpBinding();

Console.ReadLine();
}

private static void TestBasicHttpBinding()
{
ChannelFactory
<ServiceLibrary.IMyContract> channelFactory = new ChannelFactory<ServiceLibrary.IMyContract>(new BasicHttpBinding());
ServiceLibrary.IMyContract client
= channelFactory.CreateChannel(new EndpointAddress("http://localhost:8001/MyContract"));

using (client as IDisposable)
{
Console.WriteLine(
"------------TestBasicHttpBinding Begin-------------");
client.MethodWithError();
client.MethodWithoutError();
Console.WriteLine(
"------------TestBasicHttpBinding End---------------");
}
}

private static void TestNetTcpBinding()
{
ChannelFactory
<ServiceLibrary.IMyContract> channelFactory = new ChannelFactory<ServiceLibrary.IMyContract>(new NetTcpBinding());
ServiceLibrary.IMyContract client
= channelFactory.CreateChannel(new EndpointAddress("net.tcp://localhost:9001/MyContract"));

using (client as IDisposable)
{
Console.WriteLine(
"------------TestNetTcpBinding Begin-------------");
client.MethodWithError();
client.MethodWithoutError();
Console.WriteLine(
"------------TestNetTcpBinding End---------------");
}
}

 

A:测试BasicHttpBinding

首页在服务端开启:StartBasicHttpBindingServer()方法,注释StartNetTcpBindingServer()方法,在客户端开启TestBasicHttpBinding()方法,注释TestNetTcpBinding()方法,然后,先启动服务端,再启动客户端,可以看到输出如下:

服务端输出:

Please input exit to close host.
Execute MethodWithoutError
Execute MethodWithError

客户端输出:

------------TestBasicHttpBinding Begin-------------
------------TestBasicHttpBinding End---------------

      这说明没有传输会话时,服务端的异常不会传递给客户端,在服务端抛出异常后,客户端仍旧可以正常执行。

B:测试NetTcpBinding 

首页在服务端开启:StartNetTcpBindingServer()方法,注释StartBasicHttpBindingServer()方法,在客户端开启TestNetTcpBinding()方法,注释TestBasicHttpBinding()方法,然后,先启动服务端,再启动客户端,可以看到输出如下:

服务端输出:

Please input exit to close host.
Execute MethodWithError

客户端输出:

------------TestNetTcpBinding Begin-------------

同时客户端在使用相同代理进行新的调用时,抛出了错误,截图如下:

      这说明使用不包含可靠性消息传输的NetTcpBinding和NetNamedPipeBinding绑定,那么一个服务端的异常,包括单向操作抛出的异常,就会导致通道错误。

      至此,单向操作介绍完毕。

      点击下载DEMO

作者:心海巨澜
出处:http://xinhaijulan.cnblogs.com
版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

 

posted on 2010-12-19 21:57  心海巨澜  阅读(2008)  评论(3编辑  收藏  举报