Overview
In WCF, each service endpoint is associated with two addresses, one logical address and one physical address. The logical address is the target address of the SOAP message, that is, the "To" address mentioned more than once, and the physical address is the address actually listened by the WCF listener. In WCF, the logical Address is called the Endpoint Address, while the physical Address is called the listening Address ListenUri.
This article describes in detail the physical and logical addresses in WCF, and how to use tcpTrace to track SOAP messages.
Two addresses
In WCF, a physical address is used to receive incoming messages at a specific location using a specific transmission protocol. Unless otherwise specified, the logical address is used as a physical address. In other words, in the past, the EndpointAddress configured for the endpoint all specified the logical address. For example, our server configuration is as follows:
<endpoint address="http://localhost:8887/CalculatorService1" binding ="wsHttpBinding" contract="TerryLee.WCFAddressing.Contract.ICalculator"></endpoint><endpoint address="http://localhost:8887/CalculatorService2" binding ="basicHttpBinding" contract="TerryLee.WCFAddressing.Contract.ICalculator"></endpoint>
Now, we can see that the two addresses are of the same value, as shown in the following code:
using (ServiceHost calculatorServiceHost = new ServiceHost(typeof(CalculatorService))){ calculatorServiceHost.Opened += delegate { Console.WriteLine("Service begin to listen via the Address:{0}", calculatorServiceHost.BaseAddresses[0].ToString()); }; calculatorServiceHost.Open(); foreach (ServiceEndpoint se in calculatorServiceHost.Description.Endpoints) { Console.WriteLine("Endpoint details:"); Console.WriteLine("Logical address: \t{0}", se.Address); Console.WriteLine("Physical address: \t{0}", se.ListenUri); Console.WriteLine("Binding: \t{0}", se.Binding.Name); Console.WriteLine(); } Console.Read();}
Output result 1:
Figure 1
Set physical address
The Logical Address of the output result is the same as the physical address. You can set the physical address of the endpoint through code or configuration file.
WSHttpBinding wsbinding = new WSHttpBinding (); calculatorServiceHost. addServiceEndpoint (typeof (ICalculator), wsbinding, "urn: calcservice", // logical address new Uri ("http: // localhost: 8887/CalculatorService") // physical address );
Or set ListenUri through the configuration file, as shown in the following code:
<endpoint address="urn:calcservice" binding ="wsHttpBinding" contract="TerryLee.WCFAddressing.Contract.ICalculator" listenUri="http://localhost:8887/CalculatorService" bindingConfiguration="securityBinding"></endpoint>
Here, we only need to note that the relative address can still be used when specifying the physical address, which is the same as setting the logical address.
Working Principle
Now let's think about a core issue. When we define an endpoint, the WSDL contains the logical address of each endpoint, rather than the physical address. The following code snippet:
<wsdl:service name="CalculatorService"> <wsdl:port name="WSHttpBinding_ICalculator" binding="tns:WSHttpBinding_ICalculator"> <soap12:address location="urn:calcservice" /> <wsa10:EndpointReference> <wsa10:Address>urn:calcservice</wsa10:Address> </wsa10:EndpointReference> </wsdl:port></wsdl:service>
If the physical address and logical address are the same, there will be no problem, but how does the client interact with a service with different physical addresses configured? Because the client does not care whether the server has configured different physical addresses, it only knows that each endpoint has a unique endpoint address and only needs to interact with the address, this address will also be placed in the "To" header as a SOAP message.
At this time, we need a special mechanism to notify the client of the physical address to be used, and then the client sends External messages through the physical address, just as it is a router or a type of intermediary, you can achieve this through ClientViaBehavior, as shown in the following code:
<system.serviceModel> <client> <endpoint address="urn:calcservice" binding="wsHttpBinding" contract="TerryLee.WCFAddressing.Contract.ICalculator" name="defualtEndpoint" behaviorConfiguration="calculatorEndpointBehavior" bindingConfiguration="securityBinding"> </endpoint> </client> <behaviors> <endpointBehaviors> <behavior name="calculatorEndpointBehavior"> <clientVia viaUri="http://localhost:8887/CalculatorService" /> </behavior> </endpointBehaviors> </behaviors></system.serviceModel>
At this time, the client will send messages to the outside through the same physical address (http: // localhost: 8887/CalculatorService) as the service endpoint, instead of through "urn: calcservice", but please note that, the "To" header of the SOAP message still contains the logical address, as shown in Figure 2:
Figure 2
As shown in the figure above, you may have another question: what is the role of the Logical Address? Don't forget the message filtering we mentioned earlier. When the message arrives, ChannelDispatcher queries each related EndpointDispatcher object to determine whether the end point can accept the message, and pass the message to the endpoint of the acceptable message. When the target address of a message (the address in the To header) matches the AddressFilter attribute and the message operation matches the ContractFilter attribute, the EndpointDispatcher object is responsible for processing messages from ChannelDispatcher.
Physical address mode
After understanding the relationship between the physical address and the logical address, let's look at the two modes when setting the listening address, which are specified through the ListenUriMode enumeration. It defines two enumeration values:
Explicit: Use ListenUri, which is the default value.
Unique: Specifies whether a specific transmission mechanism should be used for transmission to ensure that ListenUri is unique.
Based on the protocol used for transmission, WCF uses different policies to ensure that ListenUri is unique. The specific policies are as follows:
1. For non-TCP transmission, append a GUID to the end of ListenUri.
2. For TCP in exclusive mode (PortSharingEnabled is false), bind it to a unique available port number.
3. For TCP (PortSharingEnabled is true) in Port Sharing Mode, append a GUID to the end of ListenUri.
TcpTrace message interception
The most important use of these physical and logical addresses is routing. We often use tcpTrace for SOAP message tracking. It uses this technology to configure ClientViaBehavior on the client, pointing to the listening address of tcpTrace, and then tcpTrace records the message and forwards it to the server, for example, if the server is configured as follows, its physical address and logic are the same:
<service name="TerryLee.WCFAddressing.Service.CalculatorService" behaviorConfiguration="calculatorBehavior">
Client configuration. Here "http: // localhost: 8887/CalculatorService" is the real service address (Logical Address). We use ClientViaBehavior to tell the client that the physical address is "http: // localhost: 8080/CalculatorService ". In fact, the service in this physical address does not exist. This address is the listening address of tcpTrace:
<?xml version="1.0" encoding="utf-8" ?><configuration> <system.serviceModel> <client> <endpoint address="http://localhost:8887/CalculatorService" binding="wsHttpBinding" contract="TerryLee.WCFAddressing.Contract.ICalculator" behaviorConfiguration="calculatorEndpointBehavior"> </endpoint> </client> <behaviors> <endpointBehaviors> <behavior name="calculatorEndpointBehavior"> <clientVia viaUri="http://localhost:8080/CalculatorService" /> </behavior> </endpointBehaviors> </behaviors> </system.serviceModel></configuration>
TcpTrace configuration 3 is shown in the following figure:
Figure 3
Here, the tcpTrace listening port number is the physical address port we configured on the client, and the distribution address is the real address of the service, and finally we can see the intercepted message, as shown in 4:
Figure 4
If you do not configure ClientViaBehavior on the client, you can use tcpTrace in another way by leveraging the knowledge of physical addresses and logical addresses. As I mentioned earlier, the logical address is included in the WSDL, so what the client knows is the logical address, which will send messages to the address, in this way, we can configure the Logical Address of the endpoint as the address for tcpTrace listening, specify another physical address for the server, and configure tcpTrace to forward messages to the physical address. For example, the server configuration is as follows:
<service name="TerryLee.WCFAddressing.Service.CalculatorService" behaviorConfiguration="calculatorBehavior">
The client does not need to configure ClientViaBehavior, as shown in the following code:
<?xml version="1.0" encoding="utf-8" ?><configuration> <system.serviceModel> <client> <endpoint address="http://localhost:8887/CalculatorService" binding="wsHttpBinding" contract="TerryLee.WCFAddressing.Contract.ICalculator"> </endpoint> </client> </system.serviceModel></configuration>
Now "http: // localhost: 8887/CalculatorService" is a logical address. Configure tcpTrace to listen to this address and send it to the Service's physical address "http: // localhost: 8080/CalculatorService forward messages, as shown in Figure 5:
Figure 5
We can see that the knowledge of physical addresses and logical addresses can easily implement routing. Of course, tcpTrace is only a very simple use of routing, and we will discuss more complex applications later.
Conclusion
This article describes in detail the physical and logical addresses in WCF, its principles, and how to use tcpTrace to track SOAP messages. Articles about WCF addressing:
WCF topic series (4): go deep into WCF addressing Part 4-custom message Filter
WCF topic series (3): go deep into WCF addressing Part 3-message filtering engine
WCF topic series (2): go deep into WCF addressing Part 2-custom addressing Header
WCF topic series (1): In-depth WCF addressing Part 1-Web service addressing specifications