止文(WCF學習之旅—TcpTrace工具(二十五))介紹了關於TcpTrance的一種使用方式,接下來介紹第二種使用方式。
三、通過ListenUri實現基於tcpTracer的消息路由
對於路由的實現,本質上就是實現邏輯地址和物理地址的分離。通過前面的示例介紹,我們了解,如何在客戶端實現TcpTracer捕獲客戶端與服務端的通信信息。在這一章節中我們學習如能通過設置ListenUri實現基於服務端的TcpTracer的消息路由。
服務端的物理地址和邏輯地址的分離通過ListenUri實現,ListenUri指定了服務的物理地址,大家可能覺得奇怪,我們設置服務地址的時候一般都是設 置Address(ABC的一部分),但是Address指定的是邏輯地址,而ListenUri指定的是物理地址,如果指定了這個屬性的值,那么就指定了服務的物理地址。
通過ListenUri的實現的基本原理如下圖所示:客戶端保持不變,在對服務進行寄宿的時候,將 ListenUri的端口設為8080,那么服務實際的監聽地址的端口將從8888變成8080。由於客戶端保持不變,所以請求消息仍然發送到端口 8888,為了實現TcpTracer對消息正常的路由,只需要將原端口和目的端口指定為8888(邏輯地址)和8080(物理地址)就可以了。 如下圖。
為此,我們需要修改服務寄宿的配置,在終結點配置節中指定listenUri為http://127.0.0.1:8080/BookService
<?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework,
Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> </configSections> <entityFramework> <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" /> <providers> <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" /> </providers> </entityFramework> <system.serviceModel> <bindings> <customBinding> <binding name="listenUriBinding"> <textMessageEncoding /> <httpTransport /> </binding> </customBinding> </bindings> <services> <service name="SCF.WcfService.BookService"> <endpoint address="http://127.0.0.1:8888/BookService" binding="customBinding" bindingConfiguration="listenUriBinding" listenUri="http://127.0.0.1:8080/BookService" contract="SCF.Contracts.IBookService" /> </service> </services> </system.serviceModel> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> </startup> <connectionStrings> <add name="Entities" connectionString="metadata=res://*/BookModel.csdl|res://*/BookModel.ssdl|res://*/BookModel.msl;
provider=System.Data.SqlClient;provider connection string="data source=.\SQLEXPRESS;initial catalog=Test;integrated security=SSPI;
MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" /> </connectionStrings> </configuration>
現在我們啟動tcpTracer,將Listen On Port#和Destination Port #設置為8888和8080。 如下圖。
當我們先后啟動服務寄宿和服務訪問的控制台應用程序,在tcpTracer中,我們可以得到和步驟二一樣的結果。如下圖。
注意,在實際的使用過程中,出現過以下問題。
WCF 異常:無法打開安全通道,因為與遠程終結點的安全協商已失敗。這可能是由於用於創建通道的 EndpointAddress 中不存在 EndpointIdentity
遇到這個問題我的第一反應就是客戶端和服務端的配置不同造成的。
如果是通過VS引用服務地址的方式添加的服務只要更新服務引用后這個問題就解決了。
但是如果是通過自己手寫代碼調用或是使用配置文件的就要檢查客戶端與服務端的代碼與配置文件中的信息。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> </startup> <system.serviceModel> <bindings> <wsHttpBinding> <binding name="WSHttpBinding_IBookService" /> <binding name="WSHttpBinding_IBookService1" /> </wsHttpBinding> <customBinding> <binding name="listenUriBinding"> <textMessageEncoding /> <httpTransport /> </binding> </customBinding> </bindings> <client> <endpoint address="http://127.0.0.1:8888/BookService" binding="customBinding" bindingConfiguration="listenUriBinding"
contract="SCF.Contracts.IBookService" name="WSHttpBinding_IBookService"> <identity> <userPrincipalName value="DEVELOPER\Administrator" /> </identity> </endpoint> <endpoint address="http://127.0.0.1:8888/BookService" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IBookService1" contract="BookServiceRef.IBookService" name="WSHttpBinding_IBookService1"> <identity> <userPrincipalName value="DEVELOPER\Administrator" /> </identity> </endpoint> </client> </system.serviceModel> </configuration>