1. WCF 消息交换
原文:http://www.rainsts.net/article.asp?id=428
客户端和服务之间通过消息交换(Message Exchange)来完成方法调用和数据传递,WCF 定义了 3 种消息交换模式。
1. Request/Reply
这是缺省模式,又称为同步调用。在调用服务方法后需要要等待服务消息的返回。
Public Class Service1
Implements IService1
Public Sub Run() Implements IService1.Run
Threading.Thread.Sleep(4000) '停四秒
End Sub
End Class
Implements IService1
Public Sub Run() Implements IService1.Run
Threading.Thread.Sleep(4000) '停四秒
End Sub
End Class
客户端调用
Dim s As New ServiceReference1.Service1Client
s.Open()
Console.WriteLine("开始执行时间: {0}", Now.ToString)
s.Run()
Console.WriteLine("结束执行时间:{0}", Now.ToString)
s.Close()
Console.ReadKey()
s.Open()
Console.WriteLine("开始执行时间: {0}", Now.ToString)
s.Run()
Console.WriteLine("结束执行时间:{0}", Now.ToString)
s.Close()
Console.ReadKey()
运行结果
开始执行时间: 2009-11-06 16:53:51
结束执行时间:2009-11-06 16:53:55
相差了四秒了。
2.one-way模式
这种方式在调用方法后会立即返回,非常类似于异步行为。不过需要注意的是one-way只能用在过程方法是,而不用于函数。
接口定义如下,实现不用更改
Code
<ServiceContract()> _
Public Interface IService1
<OperationContract(isoneway:=True)> _
Sub Run()
End Interface
<ServiceContract()> _
Public Interface IService1
<OperationContract(isoneway:=True)> _
Sub Run()
End Interface
我们来看一下运行结果:
开始执行时间: 2009-11-06 16:58:28
结束执行时间:2009-11-06 16:58:28
马上就返回了结果
注意使用此模式,不得声明输出参数、引用参数或返回值。
3. duplex
这种模式相对复杂一些,我们详细描述一下步骤:
(1).设计标准的服务契约。为了完成回调操作,我们必须指定SessionMode和回调类型
<ServiceContract(SessionMode:=SessionMode.Required, callbackcontract:=GetType(ICallback))> _
Public Interface IService1
<OperationContract(isoneway:=True)> _
Sub Run(ByVal name As String)
End Interface
设置回调接口类型。由于回调方法在客户端执行,因此无须加ServiceContractAttribute属性。对于回调操作,服务器无须获取返回消息,因此添加isOneWay:=True特性参数。
Codeba
Public Interface ICallback
<OperationContract()> _
Sub [Call](ByVal t As DateTime)
End Interface
Public Interface ICallback
<OperationContract()> _
Sub [Call](ByVal t As DateTime)
End Interface
实现服务契约,通过OperationContext.Current.GetCallBackChannel可以获取回调委托,进而完成调用。
Code
Public Class Service1
Implements IService1
'ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>();
Dim callback As ICallback = OperationContext.Current.GetCallbackChannel(Of ICallback)()
Public Sub Run(ByVal name As String) Implements IService1.Run
Threading.Thread.Sleep(1000) '停四秒
Me.callback.Call(Now)
Console.WriteLine("Run Time " & Now.ToString)
End Sub
End Class
Public Class Service1
Implements IService1
'ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>();
Dim callback As ICallback = OperationContext.Current.GetCallbackChannel(Of ICallback)()
Public Sub Run(ByVal name As String) Implements IService1.Run
Threading.Thread.Sleep(1000) '停四秒
Me.callback.Call(Now)
Console.WriteLine("Run Time " & Now.ToString)
End Sub
End Class
这时运行时,会出现以前异常:
System.InvalidOperationException: 协定需要双工,但是绑定“WSHttpBinding”不支持它或者因配置不正确而无法支持它。
需要更改服务器的配置文件:
<endpoint address ="" binding="wsHttpBinding" contract="异步.IService1">中的wsHttpBinding改为wsDualHttpBinding,客户端重新更新服务器引用即可
客户端实现:
Sub Main()
Dim s As New ServiceReference1.Service1Client(New System.ServiceModel.InstanceContext(New ContractCallback))
Console.WriteLine("开始执行时间: {0}", Now.ToString)
s.Run("aa")
Console.WriteLine("结束执行时间:{0}", Now.ToString)
Console.ReadKey()
End Sub
Public Class ContractCallback
Implements ServiceReference1.IService1Callback
Public Sub [Call](ByVal t As Date) Implements ServiceReference1.IService1Callback.Call
IO.File.Delete("c:\1.xml")
Console.WriteLine("Call AppDomain:" & AppDomain.CurrentDomain.FriendlyName)
Console.WriteLine("Server DateTime:" & t.ToString)
End Sub
End Class
Dim s As New ServiceReference1.Service1Client(New System.ServiceModel.InstanceContext(New ContractCallback))
Console.WriteLine("开始执行时间: {0}", Now.ToString)
s.Run("aa")
Console.WriteLine("结束执行时间:{0}", Now.ToString)
Console.ReadKey()
End Sub
Public Class ContractCallback
Implements ServiceReference1.IService1Callback
Public Sub [Call](ByVal t As Date) Implements ServiceReference1.IService1Callback.Call
IO.File.Delete("c:\1.xml")
Console.WriteLine("Call AppDomain:" & AppDomain.CurrentDomain.FriendlyName)
Console.WriteLine("Server DateTime:" & t.ToString)
End Sub
End Class
小结:
运行没有问题,但是 Call 方法,并没有进行打印,也没有删除C盘下面的1.xml文件。百思不得其解,同时反现不知道怎么调试服务端。这次虽然按照网上博客实现了三种消息传递的方式,但是没有理解其中的奥秘。