我的WCF之旅(2):Endpoint Overview

原文地址为:我的WCF之旅(2):Endpoint Overview

WCF实际上是构建了一个框架,这个框架实现了在互联系统中各个Application之间如何通信。使得Developers和Architect在构建分布式系统中,无需在考虑如何去实现通信相关的问题,更加关注与系统的业务逻辑本身。而在WCF Infrastructure中,各个Application之间的通信是由Endpoint来实现的。

Endpoint的结构

Endpoint包含以下4个对象:

  • Address: Address通过一个URI唯一地标识一个Endpoint,并告诉潜在的WCF service的调用者如何找到这个Endpoint。所以Address解决了Where to locate the WCF Service?
  • Binding: Binding实现在Client和Service通信的所有底层细节。比如Client与Service之间传递的Message是如何编码的——text/XML, binary,MTOM;这种Message的传递是采用的哪种Transport——TCP, Http, Named Pipe, MSMQ; 以及采用怎样的机制解决Secure Messaging的问题——SSL,Message Level Security。所以Binding解决的是How to communicate with service?
  • Contract: Contract的主要的作用是暴露某个WCF Service所提供的所有有效的Functionality。从Message Exchange的层面上讲,Contract实际上是抱每个Operation转化成为相对应的Message Exchange Pattern——MEP(Request/Response; One-way; Duplex)。所以Contract解决的是What functionalities do the Service provide?
  •  Behavior: Behavior的主要作用是定制Endpoint在运行时的一些必要的Behavior。比如Service 回调Client的Timeout;Client采用的Credential type;以及是否支持Transaction等。

当我们Host一个WCF Service的时候,我们必须给他定义一个或多个Endpoint,然后service通过这个定义的Endpoint进行监听来自Client端的请求。当我们的Application需要调用这个Service的时候,因为Client 和Service是通过Endpoint的进行通信的, 所以我们必须为我们的Application定义Client端的Endpoint。只有当Client的Endpoint和Service端某个Endpoint相互匹配(Service端可以为一个Service定义多个Endpoint),Client端的请求才能被Service端监听到。也就是说,我们只有在Client具有一个与Service端完全匹配的Endpoint,我们才能调用这个Service。而这种匹配是比较严格的,比如从匹配Address方面,Client端和Service端的Endpoint Address不仅仅在URI上要完全匹配Service, 他们的Headers也需要相互匹配。对于Binding, 一般地,Client需要有一个与Service端完全一样的Binding,他们之间才能通信。 

Sample

首先给一个Sample,以便我们对在WCF Service Aplication中如何定义Endpoint有一个感性的认识。整个Solution的结构参照下图,我的上一篇Blog([原创]我的WCF之旅(1):创建一个简单的WCF程序 )中有详细的介绍。你也可以通过后面的Link下载相应的Source Code(http://www.cnblogs.com/files/artech/Artech.WCFService.zip

我的WCF之旅(2):Endpoint Overview
1. Service Contract:Artech..WCfService.Contract/ServiceContract/IGeneralCalculator.cs

我的WCF之旅(2):Endpoint Overviewusing  System;
我的WCF之旅(2):Endpoint Overview
using  System.Collections.Generic;
我的WCF之旅(2):Endpoint Overview
using  System.Text;
我的WCF之旅(2):Endpoint Overview
using  System.ServiceModel;
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview
namespace  Artech.WCFService.Contract
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview {
我的WCF之旅(2):Endpoint Overview    [ServiceContract]
我的WCF之旅(2):Endpoint Overview    
public interface IGeneralCalculator
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview    
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview        [OperationContract]
我的WCF之旅(2):Endpoint Overview        
double Add(double x, double y);
我的WCF之旅(2):Endpoint Overview    }

我的WCF之旅(2):Endpoint Overview}

我的WCF之旅(2):Endpoint Overview

2. Service: Artech.WCFSerice.Service/GeneralCalculatorService.cs

我的WCF之旅(2):Endpoint Overviewusing  System;
我的WCF之旅(2):Endpoint Overview
using  System.Collections.Generic;
我的WCF之旅(2):Endpoint Overview
using  System.Text;
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview
using  Artech.WCFService.Contract;
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview
namespace  Artech.WCFService.Service
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview {
我的WCF之旅(2):Endpoint Overview    
public class GeneralCalculatorService:IGeneralCalculator
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview    
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview        
IGeneralCalculator Members#region IGeneralCalculator Members
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview        
public double Add(double x, double y)
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview        
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview            
return x + y;
我的WCF之旅(2):Endpoint Overview        }

我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview        
#endregion

我的WCF之旅(2):Endpoint Overview    }

我的WCF之旅(2):Endpoint Overview}

我的WCF之旅(2):Endpoint Overview


3. Hosting: Artech.WCFService.Hosting/Program.cs

我的WCF之旅(2):Endpoint Overviewusing  System;
我的WCF之旅(2):Endpoint Overview
using  System.Collections.Generic;
我的WCF之旅(2):Endpoint Overview
using  System.Text;
我的WCF之旅(2):Endpoint Overview
using  System.ServiceModel;
我的WCF之旅(2):Endpoint Overview
using  Artech.WCFService.Contract;
我的WCF之旅(2):Endpoint Overview
using  Artech.WCFService.Service;
我的WCF之旅(2):Endpoint Overview
using  System.ServiceModel.Description;
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview
namespace  Artech.WCFService.Hosting
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview {
我的WCF之旅(2):Endpoint Overview    
class Program
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview    
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview        
static void Main(string[] args)
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview        
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview            
//HostCalculatorServiceViaCode();
我的WCF之旅(2):Endpoint Overview
            HostCalculatorSerivceViaConfiguration();
我的WCF之旅(2):Endpoint Overview        }

我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview        
/**//// <summary>
我的WCF之旅(2):Endpoint Overview        
/// Hosting a service using managed code without any configuraiton information. 
我的WCF之旅(2):Endpoint Overview        
/// Please note that the related configuration data should be removed before calling the method.
我的WCF之旅(2):Endpoint Overview        
/// </summary>

我的WCF之旅(2):Endpoint Overview        static void HostCalculatorServiceViaCode()
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview        
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview            Uri httpBaseAddress 
= new Uri("http://localhost:8888/generalCalculator");
我的WCF之旅(2):Endpoint Overview            Uri tcpBaseAddress 
= new Uri("net.tcp://localhost:9999/generalCalculator");
我的WCF之旅(2):Endpoint Overview            
我的WCF之旅(2):Endpoint Overview            
using (ServiceHost calculatorSerivceHost = new ServiceHost(typeof(GeneralCalculatorService), httpBaseAddress, tcpBaseAddress))
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview            
我的WCF之旅(2):Endpoint Overview{           
我的WCF之旅(2):Endpoint Overview                BasicHttpBinding httpBinding 
= new BasicHttpBinding();
我的WCF之旅(2):Endpoint Overview                NetTcpBinding tcpBinding 
= new NetTcpBinding();
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview                calculatorSerivceHost.AddServiceEndpoint(
typeof(IGeneralCalculator), httpBinding, string.Empty);
我的WCF之旅(2):Endpoint Overview                calculatorSerivceHost.AddServiceEndpoint(
typeof(IGeneralCalculator), tcpBinding, string.Empty);
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview                ServiceMetadataBehavior behavior 
= calculatorSerivceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview                
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                    
if(behavior == null)
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview                    
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                        behavior 
= new ServiceMetadataBehavior();
我的WCF之旅(2):Endpoint Overview                        behavior.HttpGetEnabled 
= true;
我的WCF之旅(2):Endpoint Overview                        calculatorSerivceHost.Description.Behaviors.Add(behavior);
我的WCF之旅(2):Endpoint Overview                    }

我的WCF之旅(2):Endpoint Overview                    
else
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview                    
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                        behavior.HttpGetEnabled 
= true;
我的WCF之旅(2):Endpoint Overview                    }

我的WCF之旅(2):Endpoint Overview                }

我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview                calculatorSerivceHost.Opened 
+= delegate
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview                
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                    Console.WriteLine(
"Calculator Service has begun to listen 我的WCF之旅(2):Endpoint Overview 我的WCF之旅(2):Endpoint Overview");
我的WCF之旅(2):Endpoint Overview                }
;
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview                calculatorSerivceHost.Open();
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview                Console.Read();
我的WCF之旅(2):Endpoint Overview            }

我的WCF之旅(2):Endpoint Overview        }

我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview        
static void HostCalculatorSerivceViaConfiguration()
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview        
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview            
using (ServiceHost calculatorSerivceHost = new ServiceHost(typeof(GeneralCalculatorService)))
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview            
我的WCF之旅(2):Endpoint Overview{               
我的WCF之旅(2):Endpoint Overview                calculatorSerivceHost.Opened 
+= delegate
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview                
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                    Console.WriteLine(
"Calculator Service has begun to listen 我的WCF之旅(2):Endpoint Overview 我的WCF之旅(2):Endpoint Overview");
我的WCF之旅(2):Endpoint Overview                }
;
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview                calculatorSerivceHost.Open();
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview                Console.Read();
我的WCF之旅(2):Endpoint Overview            }

我的WCF之旅(2):Endpoint Overview        }
        
我的WCF之旅(2):Endpoint Overview    }

我的WCF之旅(2):Endpoint Overview}

我的WCF之旅(2):Endpoint Overview

4. Service.svc: http://localhost/WCFService/ GeneralCalculatorService.svc

我的WCF之旅(2):Endpoint Overview< %@ ServiceHost  Language ="C#"  Debug ="true"  Service ="Artech.WCFService.Service.GeneralCalculatorService"  % >

5. Client: Artech.WCFService.Client/ GeneralCalculatorClient.cs & Program.cs 

我的WCF之旅(2):Endpoint Overviewusing  System;
我的WCF之旅(2):Endpoint Overview
using  System.Collections.Generic;
我的WCF之旅(2):Endpoint Overview
using  System.Text;
我的WCF之旅(2):Endpoint Overview
using  System.ServiceModel;
我的WCF之旅(2):Endpoint Overview
using  System.ServiceModel.Channels;
我的WCF之旅(2):Endpoint Overview
using  Artech.WCFService.Contract;
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview
namespace  Artech.WCFService.Client
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview {
我的WCF之旅(2):Endpoint Overview    
class GeneralCalculatorClient:ClientBase<IGeneralCalculator>,IGeneralCalculator
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview    
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview        
public GeneralCalculatorClient()
我的WCF之旅(2):Endpoint Overview            : 
base()
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview        
我的WCF之旅(2):Endpoint Overview{ }
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview        
public GeneralCalculatorClient(string endpointConfigurationName)
我的WCF之旅(2):Endpoint Overview            : 
base(endpointConfigurationName)
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview        
我的WCF之旅(2):Endpoint Overview{ }
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview        
public GeneralCalculatorClient(Binding binding, EndpointAddress address)
我的WCF之旅(2):Endpoint Overview            : 
base(binding, address)
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview        
我的WCF之旅(2):Endpoint Overview{ }
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview        
IGeneralCalculator Members#region IGeneralCalculator Members
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview        
public double Add(double x, double y)
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview        
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview            
return this.Channel.Add(x, y);
我的WCF之旅(2):Endpoint Overview        }

我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview        
#endregion

我的WCF之旅(2):Endpoint Overview    }

我的WCF之旅(2):Endpoint Overview}

我的WCF之旅(2):Endpoint Overview

我的WCF之旅(2):Endpoint Overviewusing  System;
我的WCF之旅(2):Endpoint Overview
using  System.Collections.Generic;
我的WCF之旅(2):Endpoint Overview
using  System.Text;
我的WCF之旅(2):Endpoint Overview
using  System.ServiceModel;
我的WCF之旅(2):Endpoint Overview
using  System.ServiceModel.Channels;
我的WCF之旅(2):Endpoint Overview
using  Artech.WCFService.Contract;
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview
namespace  Artech.WCFService.Client
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview {
我的WCF之旅(2):Endpoint Overview    
class Program
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview    
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview        
static void Main()
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview        
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview            
try
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview            
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                
//InvocateCalclatorServiceViaCode();
我的WCF之旅(2):Endpoint Overview

我的WCF之旅(2):Endpoint Overview                InvocateCalclatorServiceViaConfiguration();
我的WCF之旅(2):Endpoint Overview            }

我的WCF之旅(2):Endpoint Overview            
catch (Exception ex)
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview            
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                Console.WriteLine(ex.Message);
我的WCF之旅(2):Endpoint Overview            }

我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview            Console.Read();    
我的WCF之旅(2):Endpoint Overview        }

我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview        
static void InvocateCalclatorServiceViaCode()
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview        
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview            Binding httpBinding 
= new BasicHttpBinding();
我的WCF之旅(2):Endpoint Overview            Binding tcpBinding 
= new NetTcpBinding();
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview            EndpointAddress httpAddress 
= new EndpointAddress("http://localhost:8888/generalCalculator");
我的WCF之旅(2):Endpoint Overview            EndpointAddress tcpAddress 
= new EndpointAddress("net.tcp://localhost:9999/generalCalculator");
我的WCF之旅(2):Endpoint Overview            EndpointAddress httpAddress_iisHost 
= new EndpointAddress("http://localhost/wcfservice/GeneralCalculatorService.svc");
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview            Console.WriteLine(
"Invocate self-host calculator service ");
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview            
Invocate Self-host service#region Invocate Self-host service
我的WCF之旅(2):Endpoint Overview            
using (GeneralCalculatorClient calculator_http = new GeneralCalculatorClient(httpBinding, httpAddress))
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview            
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                
using (GeneralCalculatorClient calculator_tcp = new GeneralCalculatorClient(tcpBinding, tcpAddress))
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview                
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                    
try
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview                    
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                        Console.WriteLine(
"Begin to invocate calculator service via http transport ");
我的WCF之旅(2):Endpoint Overview                        Console.WriteLine(
"x + y = {2} where x = {0} and y = {1}"12, calculator_http.Add(12));
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview                        Console.WriteLine(
"Begin to invocate calculator service via tcp transport ");
我的WCF之旅(2):Endpoint Overview                        Console.WriteLine(
"x + y = {2} where x = {0} and y = {1}"12, calculator_tcp.Add(12));
我的WCF之旅(2):Endpoint Overview                    }

我的WCF之旅(2):Endpoint Overview                    
catch (Exception ex)
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview                    
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                        Console.WriteLine(ex.Message);
我的WCF之旅(2):Endpoint Overview                    }

我的WCF之旅(2):Endpoint Overview                }

我的WCF之旅(2):Endpoint Overview            }

我的WCF之旅(2):Endpoint Overview            
#endregion

我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview            Console.WriteLine(
"\n\nInvocate IIS-host calculator service ");
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview            
Invocate IIS-host service#region Invocate IIS-host service
我的WCF之旅(2):Endpoint Overview            
using (GeneralCalculatorClient calculator = new GeneralCalculatorClient(httpBinding, httpAddress_iisHost))
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview            
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                
try
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview                
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                    Console.WriteLine(
"Begin to invocate calculator service via http transport ");
我的WCF之旅(2):Endpoint Overview                    Console.WriteLine(
"x + y = {2} where x = {0} and y = {1}"12, calculator.Add(12));
我的WCF之旅(2):Endpoint Overview                }

我的WCF之旅(2):Endpoint Overview                
catch (Exception ex)
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview                
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                    Console.WriteLine(ex.Message);
我的WCF之旅(2):Endpoint Overview                }

我的WCF之旅(2):Endpoint Overview            }

我的WCF之旅(2):Endpoint Overview            
#endregion

我的WCF之旅(2):Endpoint Overview        }

我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview        
static void InvocateCalclatorServiceViaConfiguration()
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview        
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview            Console.WriteLine(
"Invocate self-host calculator service ");
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview            
Invocate Self-host service#region Invocate Self-host service
我的WCF之旅(2):Endpoint Overview            
using (GeneralCalculatorClient calculator_http = new GeneralCalculatorClient("selfHostEndpoint_http"))
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview            
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                
using (GeneralCalculatorClient calculator_tcp = new GeneralCalculatorClient("selfHostEndpoint_tcp"))
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview                
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                    
try
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview                    
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                        Console.WriteLine(
"Begin to invocate calculator service via http transport ");
我的WCF之旅(2):Endpoint Overview                        Console.WriteLine(
"x + y = {2} where x = {0} and y = {1}"12, calculator_http.Add(12));
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview                        Console.WriteLine(
"Begin to invocate calculator service via tcp transport ");
我的WCF之旅(2):Endpoint Overview                        Console.WriteLine(
"x + y = {2} where x = {0} and y = {1}"12, calculator_tcp.Add(12));
我的WCF之旅(2):Endpoint Overview                    }

我的WCF之旅(2):Endpoint Overview                    
catch (Exception ex)
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview                    
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                        Console.WriteLine(ex.Message);
我的WCF之旅(2):Endpoint Overview                    }

我的WCF之旅(2):Endpoint Overview                }

我的WCF之旅(2):Endpoint Overview            }

我的WCF之旅(2):Endpoint Overview            
#endregion

我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview            Console.WriteLine(
"\n\nInvocate IIS-host calculator service ");
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview           
Invocate IIS-host service#region Invocate IIS-host service
我的WCF之旅(2):Endpoint Overview            
using (GeneralCalculatorClient calculator = new GeneralCalculatorClient("iisHostEndpoint"))
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview            
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                
try
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview                
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                    Console.WriteLine(
"Begin to invocate calculator service via http transport ");
我的WCF之旅(2):Endpoint Overview                    Console.WriteLine(
"x + y = {2} where x = {0} and y = {1}"12, calculator.Add(12));                    
我的WCF之旅(2):Endpoint Overview                }

我的WCF之旅(2):Endpoint Overview                
catch (Exception ex)
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview                
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview                    Console.WriteLine(ex.Message);
我的WCF之旅(2):Endpoint Overview                }

我的WCF之旅(2):Endpoint Overview            }

我的WCF之旅(2):Endpoint Overview            
#endregion

我的WCF之旅(2):Endpoint Overview        }

我的WCF之旅(2):Endpoint Overview    }

我的WCF之旅(2):Endpoint Overview}

我的WCF之旅(2):Endpoint Overview

6. Self-Hosting Configuration: Artech.WCFService.Hosting/App.config

我的WCF之旅(2):Endpoint Overview<? xml version="1.0" encoding="utf-8"  ?>
我的WCF之旅(2):Endpoint Overview
< configuration >
我的WCF之旅(2):Endpoint Overview  
我的WCF之旅(2):Endpoint Overview    
< system .serviceModel >
我的WCF之旅(2):Endpoint Overview        
< behaviors >
我的WCF之旅(2):Endpoint Overview            
< serviceBehaviors >
我的WCF之旅(2):Endpoint Overview                
< behavior  name ="calculatorServieBehavior" >
我的WCF之旅(2):Endpoint Overview                    
< serviceMetadata  httpGetEnabled ="true"   />
我的WCF之旅(2):Endpoint Overview                
</ behavior >
我的WCF之旅(2):Endpoint Overview            
</ serviceBehaviors >
我的WCF之旅(2):Endpoint Overview        
</ behaviors >
我的WCF之旅(2):Endpoint Overview      
我的WCF之旅(2):Endpoint Overview        
< services >
我的WCF之旅(2):Endpoint Overview            
< service  behaviorConfiguration ="calculatorServieBehavior"  name ="Artech.WCFService.Service.GeneralCalculatorService" >
我的WCF之旅(2):Endpoint Overview                 
< endpoint  address =""  binding ="basicHttpBinding"  contract ="Artech.WCFService.Contract.IGeneralCalculator" >
我的WCF之旅(2):Endpoint Overview                
</ endpoint >
我的WCF之旅(2):Endpoint Overview                
< endpoint  address =""  binding ="netTcpBinding"  contract ="Artech.WCFService.Contract.IGeneralCalculator"   />
我的WCF之旅(2):Endpoint Overview                
< host >
我的WCF之旅(2):Endpoint Overview                    
< baseAddresses >
我的WCF之旅(2):Endpoint Overview                        
< add  baseAddress ="http://localhost:8888/generalcalculator"   />
我的WCF之旅(2):Endpoint Overview                        
< add  baseAddress ="net.tcp://localhost:9999/generalCalculator"   />
我的WCF之旅(2):Endpoint Overview                    
</ baseAddresses >
我的WCF之旅(2):Endpoint Overview                
</ host >
我的WCF之旅(2):Endpoint Overview            
</ service >
我的WCF之旅(2):Endpoint Overview        
</ services >
我的WCF之旅(2):Endpoint Overview    
</ system.serviceModel >
我的WCF之旅(2):Endpoint Overview
</ configuration >
我的WCF之旅(2):Endpoint Overview

7. IIS-Host Configuration:

我的WCF之旅(2):Endpoint Overview<? xml version="1.0" ?>
我的WCF之旅(2):Endpoint Overview
< configuration  xmlns ="http://schemas.microsoft.com/.NetConfiguration/v2.0" >
我的WCF之旅(2):Endpoint Overview  
< system .serviceModel >
我的WCF之旅(2):Endpoint Overview    
< behaviors >
我的WCF之旅(2):Endpoint Overview      
< serviceBehaviors >
我的WCF之旅(2):Endpoint Overview        
< behavior  name ="calculatorServiceBehavior" >
我的WCF之旅(2):Endpoint Overview          
< serviceMetadata  httpGetEnabled  ="true" ></ serviceMetadata >
我的WCF之旅(2):Endpoint Overview        
</ behavior >
我的WCF之旅(2):Endpoint Overview      
</ serviceBehaviors >
我的WCF之旅(2):Endpoint Overview    
</ behaviors >
我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview    
< services >
我的WCF之旅(2):Endpoint Overview      
< service  name ="Artech.WCFService.Service.GeneralCalculatorService"  behaviorConfiguration ="calculatorServiceBehavior" >
我的WCF之旅(2):Endpoint Overview        
< endpoint  binding ="basicHttpBinding"  contract ="Artech.WCFService.Contract.IGeneralCalculator" ></ endpoint >
我的WCF之旅(2):Endpoint Overview      
</ service >
我的WCF之旅(2):Endpoint Overview    
</ services >
我的WCF之旅(2):Endpoint Overview  
</ system.serviceModel >
我的WCF之旅(2):Endpoint Overview  
我的WCF之旅(2):Endpoint Overview    
< system .web >
我的WCF之旅(2):Endpoint Overview        
< compilation  debug ="true" >
我的WCF之旅(2):Endpoint Overview            
< assemblies >
我的WCF之旅(2):Endpoint Overview                
< add  assembly ="System.Security, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
我的WCF之旅(2):Endpoint Overview                
< add  assembly ="Microsoft.Transactions.Bridge, Version=3.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
我的WCF之旅(2):Endpoint Overview                
< add  assembly ="SMDiagnostics, Version=3.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
我的WCF之旅(2):Endpoint Overview                
< add  assembly ="System.IdentityModel.Selectors, Version=3.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
我的WCF之旅(2):Endpoint Overview                
< add  assembly ="System.DirectoryServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
我的WCF之旅(2):Endpoint Overview                
< add  assembly ="System.Web.RegularExpressions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
我的WCF之旅(2):Endpoint Overview                
< add  assembly ="System.Transactions, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
我的WCF之旅(2):Endpoint Overview                
< add  assembly ="System.Messaging, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" />
我的WCF之旅(2):Endpoint Overview                
< add  assembly ="System.ServiceProcess, Version=2.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" /></ assemblies ></ compilation >
我的WCF之旅(2):Endpoint Overview    
</ system.web >
我的WCF之旅(2):Endpoint Overview
</ configuration >
我的WCF之旅(2):Endpoint Overview

8. Client configuration: Artech.WCFService.Client/App.config

我的WCF之旅(2):Endpoint Overview<? xml version="1.0" encoding="utf-8"  ?>
我的WCF之旅(2):Endpoint Overview
< configuration >
我的WCF之旅(2):Endpoint Overview  
< system .serviceModel >
我的WCF之旅(2):Endpoint Overview    
< client >
我的WCF之旅(2):Endpoint Overview    
< endpoint  address ="http://localhost:8888/generalCalculator"  binding ="basicHttpBinding"  contract ="Artech.WCFService.Contract.IGeneralCalculator"  name ="selfHostEndpoint_http" />
我的WCF之旅(2):Endpoint Overview       
< endpoint  address ="net.tcp://localhost:9999/generalCalculator"  binding ="netTcpBinding"  contract ="Artech.WCFService.Contract.IGeneralCalculator"  name ="selfHostEndpoint_tcp" />
我的WCF之旅(2):Endpoint Overview       
< endpoint  address ="http://localhost/wcfservice/GeneralCalculatorService.svc"  binding ="basicHttpBinding"  contract ="Artech.WCFService.Contract.IGeneralCalculator"  name ="iisHostEndpoint" />
我的WCF之旅(2):Endpoint Overview    
</ client >
我的WCF之旅(2):Endpoint Overview  
</ system.serviceModel >
我的WCF之旅(2):Endpoint Overview 
</ configuration >
我的WCF之旅(2):Endpoint Overview

如何在Application中定义Endpoint

对于Self-Host的Service,绝大部分的Endpoint相关的信息都具有两种定义方式——Managed Code 和Configuration。而对于把Service Host到IIS中的情况, Endpoint的信息一般虚拟根目录下的Web.Config中定义。一般的我们我们不推荐使用代码的方式Host和调用Service,这主要是基于以下的理由。首先我们开发的环境往往与部署的环境不尽相同,才用configuration的方式是的我们可以在部署的时候通过修改配置文件以适应新的需要。其次,对于不要出现的新的需要,比如对于一个原来只供Internet内部使用的Service,我们一般会定义一个基于TCP的Endpoint,现在出现来自于Internet的潜在用户,我们只需要通过修改Config文件的方式为这个Service添加一个新的基于Http的Endpoint就可以了。 把Endpoint的信息写在config文件中的优势在于,修改config文件的内容是不需要重新编译和重新部署的。相应的定义方式清参照以上的Sample。

下面我们来看看在host 一个Service的时候,置于配置文件的信息是如何起作用的。在上面的例子中我们通过下面一段代码Host一个Serivice(对应得Service Type是GeneralCalculatorService)。

我的WCF之旅(2):Endpoint Overviewusing  (ServiceHost calculatorSerivceHost  =   new  ServiceHost( typeof (GeneralCalculatorService)))
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview
我的WCF之旅(2):Endpoint Overview {               
我的WCF之旅(2):Endpoint Overview        calculatorSerivceHost.Opened 
+= delegate
我的WCF之旅(2):Endpoint Overview我的WCF之旅(2):Endpoint Overview         
我的WCF之旅(2):Endpoint Overview{
我的WCF之旅(2):Endpoint Overview              Console.WriteLine(
"Calculator Service has begun to listen 我的WCF之旅(2):Endpoint Overview 我的WCF之旅(2):Endpoint Overview");
我的WCF之旅(2):Endpoint Overview          }
;
我的WCF之旅(2):Endpoint Overview         calculatorSerivceHost.Open();
我的WCF之旅(2):Endpoint Overview         Console.Read();
我的WCF之旅(2):Endpoint Overview}

我的WCF之旅(2):Endpoint Overview


下面是Service相关的配置信息:

我的WCF之旅(2):Endpoint Overview< services >
我的WCF之旅(2):Endpoint Overview            
< service  behaviorConfiguration ="calculatorServieBehavior"  name ="Artech.WCFService.Service.GeneralCalculatorService" >
我的WCF之旅(2):Endpoint Overview                 
< endpoint  address =""  binding ="basicHttpBinding"  contract ="Artech.WCFService.Contract.IGeneralCalculator" >
我的WCF之旅(2):Endpoint Overview                
</ endpoint >
我的WCF之旅(2):Endpoint Overview                
< endpoint  address =""  binding ="netTcpBinding"  contract ="Artech.WCFService.Contract.IGeneralCalculator"   />
我的WCF之旅(2):Endpoint Overview                
< host >
我的WCF之旅(2):Endpoint Overview                    
< baseAddresses >
我的WCF之旅(2):Endpoint Overview                        
< add  baseAddress ="http://localhost:8888/generalcalculator"   />
我的WCF之旅(2):Endpoint Overview                        
< add  baseAddress ="net.tcp://localhost:9999/generalCalculator"   />
我的WCF之旅(2):Endpoint Overview                    
</ baseAddresses >
我的WCF之旅(2):Endpoint Overview                
</ host >
我的WCF之旅(2):Endpoint Overview            
</ service >
我的WCF之旅(2):Endpoint Overview
</ services >
我的WCF之旅(2):Endpoint Overview

首先我们创建一个ServiceHost对象calculatorSerivceHost,同时指定对用的Service Type 信息(typeof(GeneralCalculatorService))。WCF Infrastructure为在配置文件在Services Section寻找是否有相对用的service定义。在这个例子中,他会找到一个name属性为Artech.WCFService.Service.GeneralCalculatorService的Service。然后他会根据定义在Service中的Endpoint定义为calculatorSerivceHost添加相应的Endpoint。 如果有对应的Endpoint Behavior设置存在于配置文件中,这些Behavior也会设置到改Endpoint中。最后调用Open方法,calculatorSerivceHost开始监听来自Client端的请求。

Address

每一个Endpoint都必须有一个Address,Address定位和唯一标志一个Endpoint。在Managed code 中,Address由System.ServiceModel.EndpointAddress对象来表示。下面是一个Adress的结构:

  • URI:指定的Endpoint的Location。URI对于Endpoint是必须的。
  • Identity:当另一个Endpoint与此Endpoint进行消息交互时,可以获取该Identity来Authenticate正在与之进行消息交互的Endpoint是否是它所希望的。Identity对于endpoint是可选的。
  • Headers:Address可以包含一些可选的Headers, 这些header最终会加到相应的Soap Message的Header中。Header存放的多为Address相关的信息,用于进行Addressing Filter。 

Address的主要作用就是同过Uri为Service提供一个监听Address。但在某些特殊的场景中,我们可以借助Address的Headers提供一些扩展的功能。在大多数的情况下Client可以直接访问Service,换句话说,如果我们把Message 传递的路径看成是以系列连续的节点(Node)的话,Message直接从Client所在的节点(Node)传递到最终的Service的节点。但在某些情况下,考虑的实现负载平衡,安全验证等因素,我们需要在Client和最终的Service之间加入一些中间节点(Intermediaries),这些中间节点可以在Message到达最终Service Node之前作一些工作,比如为了实现负载平衡,它可以把Message Request分流到不同的节点——Routing;为了在Message达到最终Node之前,验证Client是否是一个合法的请求,他可以根据Message存储的Credential的信息验证该请求——Authentication。
这些Intermediaries操作的一般不会是Message Body的内容(大多数情况下他们已经被加密),而是Message Header内容。他们可以修改Header的内容,也可以加入一些新的Header。所以为了实现Routing,我们需要在Message加入一些Addressing相关的内容,为了实现Authentication我们需要加入Client Credential的信息, 而这些信息都放在Header中。实际上你可以把很多内容加到Header中。
我们可以通过config文件加入这些Header:

我的WCF之旅(2):Endpoint Overview< service  behaviorConfiguration ="calculatorServieBehavior"  name ="Artech.WCFService.Service.DuplexCalculatorService" >
我的WCF之旅(2):Endpoint Overview                
< endpoint  binding ="wsDualHttpBinding"  contract ="Artech.WCFService.Contract.IDuplexCalculator" >
我的WCF之旅(2):Endpoint Overview                    
< headers >
我的WCF之旅(2):Endpoint Overview                        
< role > admin </ role >
我的WCF之旅(2):Endpoint Overview                    
</ headers >
我的WCF之旅(2):Endpoint Overview                
</ endpoint >
我的WCF之旅(2):Endpoint Overview                
< host >
我的WCF之旅(2):Endpoint Overview                    
< baseAddresses >
我的WCF之旅(2):Endpoint Overview                        
< add  baseAddress ="http://localhost:7777/DuplexCalculator"   />
我的WCF之旅(2):Endpoint Overview                    
</ baseAddresses >
我的WCF之旅(2):Endpoint Overview                
</ host >
我的WCF之旅(2):Endpoint Overview            
</ service >
我的WCF之旅(2):Endpoint Overview

我的WCF之旅(2):Endpoint Overview< client >
我的WCF之旅(2):Endpoint Overview      
< endpoint  address ="http://localhost/WCFService/SessionfulCalculatorService.svc"
我的WCF之旅(2):Endpoint Overview        binding
="wsHttpBinding"  bindingConfiguration =""  contract ="Artech.WCFService.Contract.ISessionfulCalculator"   >
我的WCF之旅(2):Endpoint Overview
< headers >
我的WCF之旅(2):Endpoint Overview         
< role > admin </ role >
我的WCF之旅(2):Endpoint Overview                    
</ headers >
我的WCF之旅(2):Endpoint Overview                
</ endpoint >
我的WCF之旅(2):Endpoint Overview    
</ client >
我的WCF之旅(2):Endpoint Overview

Binding

WCF,顾名思义就是实现了分布式系统中各Application之间的Communication的问题。上面我们说过, Client和Service之间的通信完全有他们各自的Endpoint的担当。Address解决了寻址的问题,通过Address,Client知道在哪里可以找到它所希望的Service。但是知道了地址,只是实现的通信的第一步。

对于一个基于SOA的分布式系统来说,各Application之间的通信是通过Message Exchange来实现的。如何实现在各个Application之间 进行Message的交互,首先需要考虑的是采用怎样的Transport,是采用Http呢,还是采用TCP或是其他,比如Named Pipe、MSMQ。其次需要考虑的是Message应该采取怎样的编码,是text/XML呢,还是Binary,或是MTOM;此外,对于一个企业级的分布式应用,Security与Robustness是我们必须考虑的问题——我们应该采用Transport Level的Security(SSL)还是Message Level的Security;如何确保我们的Message的传递是可靠的(Reliable Messaging); 如何把在各application中执行的操作纳入同一个事物中(Transaction)。而这一些都是Binding需要解决的问题。所以我们可以说Binding实现了Client和Service通信的所有底层细节。

在WCF中,Binding一个Binding Element的集合,每个Binding Element解决Communication的某一个方面。所有的Binding Element大体上可以分为以下3类:

1. Transport Binding Element:实现Communication的Transport选取,每个Binding必须包含一格Transport Element。

2. Encoding Binding Element:解决传递数据的编码的问题,每个Binding必须包含一个Encoding Element,一般由Transport Binding Element来提供。

3. Protocol Binding Element:解决Security,Reliable Messaging和Transaction的问题。

下边这个表格列出了Binding中的各个层次结构。

Layer

Options

Required

Transactions

TransactionFlowBindingElement

No

Reliability

ReliableSessionBindingElement

No

Security

SecurityBindingElement

No

Encoding

Text, Binary, MTOM, Custom

Yes

Transport

TCP, Named Pipes, HTTP, HTTPS, MSMQ, Custom

Yes


WCF相关内容:
[原创]我的WCF之旅(1):创建一个简单的WCF程序
[原创]我的WCF之旅(2):Endpoint Overview
[原创]我的WCF之旅(3):在WCF中实现双向通信(Bi-directional Communication)
[原创]我的WCF之旅(4):WCF中的序列化(Serialization)- Part I
[原创]我的WCF之旅(4):WCF中的序列化(Serialization)- Part II
[原创]我的WCF之旅(5):Service Contract中的重载(Overloading)
[原创]我的WCF之旅(6):在Winform Application中调用Duplex Service出现TimeoutException的原因和解决方案
[原创]我的WCF之旅(7):面向服务架构(SOA)和面向对象编程(OOP)的结合——如何实现Service Contract的继承
[原创]我的WCF之旅(8):WCF中的Session和Instancing Management
[原创]我的WCF之旅(9):如何在WCF中使用tcpTrace来进行Soap Trace
[原创]我的WCF之旅(10): 如何在WCF进行Exception Handling
[原创]我的WCF之旅(11):再谈WCF的双向通讯-基于Http的双向通讯 V.S. 基于TCP的双向通讯

[原创]我的WCF之旅(12):使用MSMQ进行Reliable Messaging
[原创]我的WCF之旅(13):创建基于MSMQ的Responsive Service


转载请注明本文地址:我的WCF之旅(2):Endpoint Overview