一、
在前一章中主要介绍了服务端的监听地址与逻辑地址。本节模拟消息转发机制来实际体验一把终结点的监听地址是如何使用的。
先下载一个叫做TcpTrace的小软件(108k),它能够截取端口消息,并转发消息。
先来看看服务端代码,服务端的绑定使用WS2007HttpBinding的不加密模式,因为我们等会还要看TcpTrace捕获的数据明文,所以不能加密。客户端也是使用不加密的WS2007HttpBinding。
using System.ServiceModel;using System.ServiceModel.Description;using System.ServiceModel.Channels;namespace host{ class Program { static void Main(string[] args) { using (ServiceHost host = new ServiceHost(typeof(mywcf.Calculator))) { WS2007HttpBinding bind = new WS2007HttpBinding(); WSHttpSecurity security = new WSHttpSecurity(); security.Mode = SecurityMode.None; bind.Security = security; host.AddServiceEndpoint(typeof(mywcf.ICalculator), bind, "http://localhost:8888"); host.Opened += delegate { Console.WriteLine("Service Start!"); }; host.Open(); Console.ReadLine(); } } }}
服务端发布一个终结点。由前一章说道,默认逻辑地址与监听地址一致,都是http://localhost:8888。
客户端代码如下:
using System.ServiceModel;using System.ServiceModel.Description;using System.ServiceModel.Channels;namespace client{ class Program { static void Main(string[] args) { WS2007HttpBinding bind = new WS2007HttpBinding(); WSHttpSecurity security = new WSHttpSecurity(); security.Mode = SecurityMode.None; bind.Security = security; EndpointAddress endpint=new EndpointAddress("http://localhost:8888"); mywcf.ICalculator client = ChannelFactory<mywcf.ICalculator>.CreateChannel(bind, endpint, new Uri("http://localhost:9999")); Console.WriteLine(client.Add(1, 2)); } }}
先启动服务端,再启动客户端。客户端报了一个错误,无法找到正确的终结点。
客户端的访问的逻辑地址为http://localhost:8888,监听地址为http://localhost:9999。但是服务端监听的是8888,并没有监听9999,所以访问失败。我们现在利用TcpTrace工具,把服务端9999端口收到的消息转发至服务端8888端口,服务端就能够正确的接收到请求。
点击OK,现在再次先后启动服务端和客户端,访问成功,并且已经成功转发。
现在分析一下消息内容。客户端请求<To>报头为逻辑地址为localhost:8888,目标地址为localhost:9999,<Body>为x=1,y=2,请求Add操作。下面服务端返回成功,<AddResult>为3。正因为客户端的<To>逻辑地址与服务端的逻辑地址一致,才可以通过终结点的消息筛选器。
二、
若服务端代码不变,服务端的逻辑地址和监听地址依然是8888,现在将客户端的逻辑地址和监听地址都设置为9999,再通过TcpTrace转发,将9999端口消息转发到8888端口。
客户端代码如下:
using System.ServiceModel; using System.ServiceModel.Description; using System.ServiceModel.Channels; namespace client { class Program { static void Main(string[] args) { WS2007HttpBinding bind = new WS2007HttpBinding(); WSHttpSecurity security = new WSHttpSecurity(); security.Mode = SecurityMode.None; bind.Security = security; EndpointAddress endpint=new EndpointAddress("http://localhost:9999"); mywcf.ICalculator client = ChannelFactory<mywcf.ICalculator>.CreateChannel(bind, endpint); Console.WriteLine(client.Add(1, 2)); } } }
先后运行客户端与服务端,发现报了一个异常。
再来看看TcpTrace截取的请求消息:
<To>报头地址的端口变成了9999。即使TcpTrace进行了转发,因为逻辑地址不匹配,这样的消息无法通过服务端终结点的地址筛选器。
三、
如果想让上述客户端能够正常访问服务端。在自定义的类库的服务行为将AddressFilterMode设置成AddressFilterMode.Any,即使请求的<To>逻辑地址与服务端终结点逻辑地址不一致也可以访问。
using System.ServiceModel; namespace mywcf { [ServiceBehavior(AddressFilterMode=AddressFilterMode.Any)] public class Calculator : ICalculator { public int Add(int x, int y) { return x + y; } } }