• WCF —— Endpoint & Binding & netTcpBinding Overview(转发)


    相关资料

    [原创]我的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

    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,他们之间才能通信。 

    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中。

    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

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using Artech.WCFService.Contract;

    namespace Artech.WCFService.Client
    {
        class Program
        {
            static void Main()
            {
                try
                {
                    //InvocateCalclatorServiceViaCode();

                    InvocateCalclatorServiceViaConfiguration();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }

                Console.Read();    
            }

            static void InvocateCalclatorServiceViaCode()
            {
                Binding httpBinding = new BasicHttpBinding();
                Binding tcpBinding = new NetTcpBinding();

                EndpointAddress httpAddress = new EndpointAddress("http://localhost:8888/generalCalculator");
                EndpointAddress tcpAddress = new EndpointAddress("net.tcp://localhost:9999/generalCalculator");
                EndpointAddress httpAddress_iisHost = new EndpointAddress("http://localhost/wcfservice/GeneralCalculatorService.svc");

                Console.WriteLine("Invocate self-host calculator service ");

                #region Invocate Self-host service
                using (GeneralCalculatorClient calculator_http = new GeneralCalculatorClient(httpBinding, httpAddress))
                {
                    using (GeneralCalculatorClient calculator_tcp = new GeneralCalculatorClient(tcpBinding, tcpAddress))
                    {
                        try
                        {
                            Console.WriteLine("Begin to invocate calculator service via http transport ");
                            Console.WriteLine("x + y = {2} where x = {0} and y = {1}", 1, 2, calculator_http.Add(1, 2));

                            Console.WriteLine("Begin to invocate calculator service via tcp transport ");
                            Console.WriteLine("x + y = {2} where x = {0} and y = {1}", 1, 2, calculator_tcp.Add(1, 2));
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                        }
                    }
                }
                #endregion

                Console.WriteLine("\n\nInvocate IIS-host calculator service ");

                #region Invocate IIS-host service
                using (GeneralCalculatorClient calculator = new GeneralCalculatorClient(httpBinding, httpAddress_iisHost))
                {
                    try
                    {
                        Console.WriteLine("Begin to invocate calculator service via http transport ");
                        Console.WriteLine("x + y = {2} where x = {0} and y = {1}", 1, 2, calculator.Add(1, 2));
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
                #endregion
            }

            static void InvocateCalclatorServiceViaConfiguration()
            {
                Console.WriteLine("Invocate self-host calculator service ");

                #region Invocate Self-host service
                using (GeneralCalculatorClient calculator_http = new GeneralCalculatorClient("selfHostEndpoint_http"))
                {
                    using (GeneralCalculatorClient calculator_tcp = new GeneralCalculatorClient("selfHostEndpoint_tcp"))
                    {
                        try
                        {
                            Console.WriteLine("Begin to invocate calculator service via http transport ");
                            Console.WriteLine("x + y = {2} where x = {0} and y = {1}", 1, 2, calculator_http.Add(1, 2));

                            Console.WriteLine("Begin to invocate calculator service via tcp transport ");
                            Console.WriteLine("x + y = {2} where x = {0} and y = {1}", 1, 2, calculator_tcp.Add(1, 2));
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                        }
                    }
                }
                #endregion

                Console.WriteLine("\n\nInvocate IIS-host calculator service ");

               #region Invocate IIS-host service
                using (GeneralCalculatorClient calculator = new GeneralCalculatorClient("iisHostEndpoint"))
                {
                    try
                    {
                        Console.WriteLine("Begin to invocate calculator service via http transport ");
                        Console.WriteLine("x + y = {2} where x = {0} and y = {1}", 1, 2, calculator.Add(1, 2));                    
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
                #endregion
            }
        }
    }

    我的WCF之旅(3):在WCF中实现双工通信

    一、两种典型的双工MEP

    1.请求过程中的回调

    这是一种比较典型的双工消息交换模式的表现形式,客户端在进行服务调用的时候,附加上一个回调对象;服务在对处理该处理中,通过客户端附加的回调对象(实际上是调用回调服务的代理对象)回调客户端的操作(该操作在客户端执行)。整个消息交换的过程实际上由两个基本的消息交换构成,其一是客户端正常的服务请求,其二则是服务端对客户端的回调。两者可以采用请求-回复模式,也可以采用单向(One-way)的MEP进行消息交换。图1描述了这样的过程,服务调用和回调都采用请求-回复MEP。

     


    图1 请求过程中的回调

    2.订阅-发布

    订阅-发布模式是双工模式的一个典型的变体。在这个模式下,消息交换的双方变成了订阅者和发布者,若干订阅者就某个主题向发布者申请订阅,发布者将所有的订阅者保存在一个订阅者列表中,在某个时刻将主题发送给该主题的所有订阅者。实际上基于订阅-发布模式的消息交换也可以看成是两个基本模式下消息交换的组合,申请订阅是一个单向模式的消息交换(如果订阅者行为得到订阅的回馈,该消息交换也可以采用请求-回复模式);而主题发布也是一个基于单向模式的消息交换过程。订阅-发布消息交换模式如图2所示。

     


    图2 订阅-发布

    我的WCF之旅(7):面向服务架构(SOA)和面向对象编程(OOP)的结合——如何实现Service Contract的继承

    我的WCF之旅(9):如何在WCF中使用tcpTrace来进行Soap Trace

    无论对于Web Service还是WCF,Client和Service之间交互的唯一形式是通过发送和接收Soap Message。在我们对Web Service和WCF进行深入学习的时候,借助一些Soap Trace 工具对Soap Message进行深入剖析是非常有必要的。在这些工具之中,我觉得最好用的就是Microsoft Soap Toolkit中的Soap Trace Utility和tcpTrace。我们今天就来讲讲如何在WCF中使用tcpTrace这个工具。

    首先我们来讲讲tcpTrace实现的基本原理。说的简单点TcpTrace就是一个监听/转发器(Listening/Forwarding)。当我们启动这个工具的时候,通过设置它监听的Port,和它将要转发的Host和Port(Destination Server& Destination Port),随后它就开始在本机的Listening Port开始监听,如果这时候一个针对该Listening Port 的Http Request,它就会把Request的内容取下来展现在我们的面前,随后将该Request转发到我们预先设定的Host和Port。

    对于WCF来说,如果Client要访问Service,一般情况下交互的只有Client和Service,Soap Message直接从Client到Service。但是在某些情况,我们需要在Client和Service之间加入一些额外的节点,我们把这些额外的节点Intermediary Node。我们可以通过这些Intermediary Node实现一些额外的功能,比如把不同的Request forward到不同的Server从而实现负载平衡(Load Balance)。按照面向服务的原则,服务具有高度的自治性(Automation),Soap Message一旦被Service发送出去,就不能再被该Service所控制,所以Soap来说,它需要具有高度的自描述性(Self-Describing),它自身必须包含所有必须的控制信息来指导任何接收到该Soap的节点如何去处理它。SOAP的无限扩展的Header在实现此功能上可谓功不可没,原则上任何控制信息都可以放在Soap Header之中,Header的可扩展性也使一系列的WS-* Specification的实现 成为可能。对于每次的Message Exchange来说,寻址(Addressing)是首先需要解决的问题,在Intermediary Node的场景中,实际上涉及到两个Address,其中一个是最终Service Endpoint的Address,另一个则是实际接收该Soap的Intermediary Node的Address。在WCF中通过ClientViaBehavior实现这样的功能,我将在 后面讲到。而我们今天所介绍的通过tcpTrace来获取Soap的情况下,tcpTrace实际是就是充当了Intermediary Node的角色。

    我的WCF之旅(10):如何在WCF进行Exception Handling

    在任何Application的开发中,对不可预知的异常进行troubleshooting时,异常处理显得尤为重要。对于一般的.NET系统来说,我们简单地借助try/catch可以很容易地实现这一功能。但是对于 一个分布式的环境来说,异常处理就没有那么简单了。按照面向服务的原则,我们把一些可复用的业务逻辑以Service的形式实现,各个Service处于一个自治的环境中,一个Service需要和另一个Service进行交互,只需要获得该Service的描述(Description)就可以了(比如WSDL,Schema和Strategy)。借助标准的、平台无关的通信构架,各个Service之间通过标准的Soap Message进行交互。Service Description、Standard Communication Infrastructure、Soap Message based Communication促使各Service以松耦合的方式结合在一起。但是由于各个Service是自治的,如果一个Service调用另一个Service,在服务提供方抛出的Exception必须被封装在Soap Message中,方能被处于另一方的服务的使用者获得、从而进行合理的处理。下面我们结合一个简单的Sample来简单地介绍我们可以通过哪些方式在WCF中进行Exception Handling。

    我的WCF之旅 (11): 再谈WCF的双向通讯-基于Http的双向通讯 V.S. 基于TCP的双向通讯

    在一个基于面向服务的分布式环境中,借助一个标准的、平台无关的Communication Infrastructure,各个Service通过SOAP Message实现相互之间的交互。这个交互的过程实际上就是Message Exchange的过程。WCF支持不同形式的Message Exchange,我们把这称之为Message Exchange Pattern(MEP), 常见的MEP包括: Request/Reply,Request/Forget(One-way)和Duplex。通过采用Duplex MEP,我们可以实现在Service端Callback Client的操作。虽然WCF为我们实现底层的通信细节,使得我们把精力转移到业务逻辑的实现,进行Transport无关的编程,但是对底层Transport的理解有利于我们根据所处的具体环境选择一个合适的Transport。说到Transport, WCF 经常使用的是以下4个:Http,TCP,Named Pipe,MSMQ。由于不同协议自身的差异,他们对具体MEP的支持方式也会不同,我们今天就来谈谈Http和TCP对Duplex的支持。

     基于Http的双向通讯V.S.基于TCP的双向通讯

    由于Http和TCP在各自协议上的差异,他们实现双向通信的发式是不同的。

    Http是一个应用层的协议,它的主要特征就是无连接和无状态(connectless & stateless )。它采用传统的Request/Reply的方式进行通信,Client发送Http Request请求Server的某个资源,Server端接收到该Http Request, 回发对应的Http Response。当Client端接收到对应的Response,该Connection会关闭。也就是说Client和Server的Connection仅仅维持在发送Request到接收到Response这一段时间内。同时,每次基于Http的 connection是相互独立,互不相干的,当前connection无法获得上一次connection的状态。为了保存调用的的状态信息,ASP.NET通过把状态信息保存在Server端的方式实现了对Session的支持,具体的做法是:ASP.NET为每个Session创建一个Unique ID,与之关联一个HttpSessionState对象,并把状态信息保存在内存中或者持久的存储介质(比如SQL Server)中。而WCF则采用另外的方式实现对Session的支持:每个Session关联到某个Service Instance上。

    回到我们WCF双向通信的问题上,当Client调用Service之前,会有一个Endpoint在Client端被创建,用于监听Service端对它的Request。Client对Service的调用会建立一个Client到Server的Connection,当Service在执行操作过程中需要Callback对应的Client,实际上会建立另一个Service到Client的Http connection。虽然我们时候说WCF为支持双向通信提供Duplex Channel,实际上这个Duplex channel是由两个Request/Reply Channel组成的。

    而对于TCP/IP簇中的传输层协议TCP,它则是一个基于Connection的协议,在正式进行数据传输的之前,必须要在Client和Server之后建立一个Connection,Connection的建立通过经典的“3次握手”来实现。TCP天生就具有Duplex的特性,也就是说当Connection被创建之后,从Client到Sever,和从Server到Client的数据传递都可以利用同一个Connection来实现。对于WCF中的双向通信,Client调用Service,Service Callback Client使用的都是同一个Connection、同一个Channel。所以基于TCP的Duplex Channel才是真正意义上的Duplex Channel。

    WCF简单教程(2) 聊聊binding

    聊聊binding

    上一篇构建的WCF程序,binding指定的是basicHttpBinding,这是最基础的通讯方式,基于http,不加密,抓一下包的话,应该是这样的:

    发送包: 
    POST /wcf HTTP/1.1 
    Content-Type: text/xml; charset=utf-8 
    SOAPAction: "WCF.Demo/IData/SayHello" 
    Host: 127.0.0.1:8080 
    Content-Length: 156 
    Expect: 100-continue 
    Connection: Keep-Alive 
     
    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><SayHello xmlns="WCF.Demo"><userName>WCF</userName></SayHello></s:Body></s:Envelope> 
     
    -------------------------
    应答包: 
    HTTP/1.1 100 Continue 
     
    HTTP/1.1 200 OK 
    Content-Length: 191 
    Content-Type: text/xml; charset=utf-8 
    Server: Microsoft-HTTPAPI/2.0 
    Date: Mon, 05 Mar 2012 08:45:31 GMT 
     
    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><SayHelloResponse xmlns="WCF.Demo"><SayHelloResult>Hello WCF.</SayHelloResult></SayHelloResponse></s:Body></s:Envelope> 

    就是SOAP,和WebService是一样的。basicHttpBinding的优势在于通用,又基于http,所以在跨语言的开发中或者是穿透复杂网络环境时占优势,但是效率比较低,因为SOAP的序列化和反序列化比较耗时,传输的数据量也比较大,而且是明文,安全性差。

    WCF的binding有很多种,包括:
    basicHttpBinding(常用) 符合WSBasicProfile 1.1标准,以提供最大的互操作性
    wsHttpBinding(常用)  符合WS-*协议的HTTP通讯,加密 
    wsDualHttpBinding  双工http通信,初始信息的接收者不会直接响应发送者,而是可以在一定时间之内传送任意次的响应 
    wsFederationBinding  http通信,对服务资源的访问可以根据一个显式确定的凭据提供程序发出的凭据加以控制 
    netTcpBinding(常用)  提供网络里WCF软件实体之间的安全可靠高性能的通信 
    netNamedPipeBinding  同一台机器上的WCF软件实体之间的安全可靠高性能的通信 
    netMsmqBinding  WCF软件实体与其它软件实体间通过MSMQ通信 
    msmqIntegrationBinding 软件实体与其它软件实体间通过MSMQ通信 
    netPeerTcpBinding  WCF软件实体间通过Windows对等网络技术通信 
    内容很多,我们挑wsHttpBinding和netTcpBinding继续研究一下,这两个最有代表性。在上一篇demo的基础上修改一下。

    1、服务端

    服务端的功能逻辑没有任何变化,只是调整绑定方式,所以只调整App.config:

    <?xml version="1.0" encoding="utf-8" ?>  
    <configuration>  
      <system.serviceModel>  
        <services>  
          <service name="Server.DataService">  
            <host>  
              <baseAddresses>  
                <add baseAddress="http://localhost:8080/wcf" /> 
                <!-- 此处增加了个baseAddress,注意标头指定的是net.tcp,另外端口不能被占用 --> 
                <add baseAddress="net.tcp://localhost:8081/wcf" /> 
              </baseAddresses>  
            </host>  
    <!-- 此处调整了绑定使用wsHttpBinding方式 --> 
            <endpoint address="" binding="wsHttpBinding" contract="Server.IData" /> 
            <!-- 此处增加了一个endpoint,使用netTcpBinding方式,服务契约同样是IData --> 
            <endpoint address="" binding="netTcpBinding" contract="Server.IData" /> 
          </service>  
        </services>  
      </system.serviceModel>  
    </configuration>  

    与之前相比,增加了一个baseAddress和一个endpoint,另外调整了之前endpoint的绑定方式。现在针对同一个服务契约,有两个endpoint了,但是它们不会冲突,因为两者的网络协议不同,所以wsHttpBinding的会使用http://localhost:8080/wcf的地址,而netTcpBinding的会使用net.tcp://localhost:8081/wcf的地址。

    如果同时定义了basicHttpBinding和wsHttpBinding呢?那么它们的address一定不能相同,因为baseAddress已经相同了,adress还一样,就无法访问了。

    编译运行一下,然后命令行“netstat -ano”看一下,应该能看到8080和8081都开始监听了。

    TCP    0.0.0.0:8080        0.0.0.0:0          LISTENING       4 
    TCP    0.0.0.0:8081        0.0.0.0:0          LISTENING       692 
    TCP    [::]:8080           [::]:0             LISTENING       4 
    TCP    [::]:8081           [::]:0             LISTENING       692 

    TCP 8081端口的PID显示是我们的服务程序在对外监听。

    2、客户端

    由于服务端修改了绑定方式,客户端必须要与之匹配,先修改App.config文件:

    <?xml version="1.0" encoding="utf-8" ?>  
    <configuration>  
      <system.serviceModel>  
        <client>  
          <!-- 此处调整了binding为wsHttpBinding --> 
          <endpoint name="httpDataService" address="http://localhost:8080/wcf" binding="wsHttpBinding" contract="Server.IData" /> 
          <!-- 此处新增了一个endpoint,指定使用netTcpBinding方式 --> 
          <endpoint name="tcpDataService" address="net.tcp://localhost:8081/wcf" binding="netTcpBinding" contract="Server.IData" /> 
        </client>  
      </system.serviceModel>  
    </configuration>  

    需要指出的是,服务端开放了2种访问方式,客户端不一定也要写2个endpoint,这里是为了测试两种绑定。

    调用代码也要做个小修改:

    using System; 
    using System.ServiceModel; 
    using System.ServiceModel.Channels; 
     
    namespace Client 

        class Program 
        { 
            static void Main(string[] args) 
            { 
             //定义一个http方式的代理,配置使用httpDataService中的定义 
                var httpProxy = new ChannelFactory<Server.IData>("httpDataService").CreateChannel(); 
                Console.WriteLine(httpProxy.SayHello("WCF")); 
                ((IChannel)httpProxy).Close(); 
     
             //定义一个tcp方式的代理,配置使用tcpDataService中的定义 
                var tcpProxy = new ChannelFactory<Server.IData>("tcpDataService").CreateChannel(); 
                Console.WriteLine(tcpProxy.SayHello("WCF")); 
                ((IChannel)tcpProxy).Close(); 
            } 
        } 


    编译运行一下,应该能够输出两行 Hello WCF.。

    抓包看看:

    wsHttpBinding方式的客户端与服务端总共交换了60多个数据包,这是因为双方要先握手交换密钥,另外由于数据加了密,长度也变大了。这里只截第一次交互的数据看看:

    发送包: 
    POST /wcf HTTP/1.1 
    Content-Type: application/soap+xml; charset=utf-8 
    Host: 127.0.0.1:8080 
    Content-Length: 1106 
    Expect: 100-continue 
    Connection: Keep-Alive 
     
    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header><a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action><a:MessageID>urn:uuid:144b8aeb-6ac1-46f5-8361-957425b827c8</a:MessageID><a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo><a:To s:mustUnderstand="1">http://192.168.90.81:8080/wcf</a:To></s:Header><s:Body><t:RequestSecurityToken Context="uuid-156d27d6-3db7-43ac-b488-12f9ae123861-1" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust"><t:TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</t:TokenType><t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType><t:KeySize>256</t:KeySize><t:BinaryExchange ValueType="http://schemas.xmlsoap.org/ws/2005/02/trust/spnego" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">TlRMTVNTUAABAAAAt7IY4gkACQAxAAAACQAJACgAAAAGAbAdAAAAD1RJQU5ZVS1QQ1dPUktHUk9VUA==</t:BinaryExchange></t:RequestSecurityToken></s:Body></s:Envelope> 
     
    --------------------- 
    应答包: 
    HTTP/1.1 100 Continue 
     
    HTTP/1.1 200 OK 
    Content-Length: 1044 
    Content-Type: application/soap+xml; charset=utf-8 
    Server: Microsoft-HTTPAPI/2.0 
    Date: Tue, 06 Mar 2012 01:46:24 GMT 
     
    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header><a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue</a:Action><a:RelatesTo>urn:uuid:144b8aeb-6ac1-46f5-8361-957425b827c8</a:RelatesTo></s:Header><s:Body><t:RequestSecurityTokenResponse Context="uuid-156d27d6-3db7-43ac-b488-12f9ae123861-1" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><t:BinaryExchange ValueType="http://schemas.xmlsoap.org/ws/2005/02/trust/spnego" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">TlRMTVNTUAACAAAAEgASADgAAAA1wprik+hmjwEji3X4ciEAAAAAAGgAaABKAAAABgGwHQAAAA9UAEkAQQBOAFkAVQAtAFAAQwACABIAVABJAEEATgBZAFUALQBQAEMAAQASAFQASQBBAE4AWQBVAC0AUABDAAQAEgBUAGkAYQBuAFkAdQAtAFAAQwADABIAVABpAGEAbgBZAHUALQBQAEMABwAIAPm5CvA6+8wBAAAAAA==</t:BinaryExchange></t:RequestSecurityTokenResponse></s:Body></s:Envelope> 

    应该是双方交换了一个256位的密钥,反正所有的数据交互都不再是明文的了。

    再来看netTcpBinding的这次,还是只截一小段吧:

    发送包: 
    00000000  00 01 00 01 02 02 20 6E  65 74 2E 74 63 70 3A 2F   ...... n et.tcp:/  
    00000010  2F 31 39 32 2E 31 36 38  2E 39 30 2E 38 31 3A 38   /192.168 .90.81:8  
    00000020  30 38 31 2F 77 63 66 03  08 09 15 61 70 70 6C 69   081/wcf. ...appli  
    00000030  63 61 74 69 6F 6E 2F 6E  65 67 6F 74 69 61 74 65   cation/n egotiate  
    00000040  16 01 00 00 3A 4E 54 4C  4D 53 53 50 00 01 00 00   ....:NTL MSSP....  
    00000050  00 B7 B2 18 E2 09 00 09  00 31 00 00 00 09 00 09   ........ .1..... 
     
    ---------- 
    应答包: 
    00000000  0A 16 01 00 00 B2 4E 54  4C 4D 53 53 50 00 02 00   ......NT LMSSP...  
    00000010  00 00 12 00 12 00 38 00  00 00 35 C2 9A E2 3A D5   ......8. ..5...:.  
    00000020  19 64 33 D4 B9 7C F8 72  21 00 00 00 00 00 68 00   .d3..|.r !.....h.  
    00000030  68 00 4A 00 00 00 06 01  B0 1D 00 00 00 0F 54 00   h.J..... ......T.  
    00000040  49 00 41 00 4E 00 59 00  55 00 2D 00 50 00 43 00   I.A.N.Y. U.-.P.C.  
    00000050  02 00 12 00 54 00 49 00  41 00 4E 00 59 00 55 00   ....T.I. A.N.Y.U.  

    从效率上讲,tcp方式要比http方式高得多,同时http方式,basicHttpBinding又要比wsHttpBinding高得多,在实际使用中,大家要看需求来决定使用哪种方式。

    OK,下一篇我们看看能不能不用写复杂的配置就发布WCF服务,也以此来加深一下对Host、Contract、Binding、BaseAddress的理解。

     

    -----------------------------------
    ©著作权归作者所有:来自51CTO博客作者BoyTNT的原创作品,请联系作者获取转载授权,否则将追究法律责任
    WCF简单教程(2) 聊聊binding
    https://blog.51cto.com/boytnt/796993

    WCF之Binding详解

    WCF中的 Binding是什么?

    在弄清Binding是什么之前,我们先 看一下WCF的中的Endpoint结构,一个Endpoint就类似于xml web service中的一个asmx文件,它包括三个组成部分1)Address 2) Binding 3) Contract,此三者被称为组成Endpoint的"ABC",下图阐述了Endpoint的组成结构:

    ABC分别解决了Endpoint的如下问题:

    A解决了Endpoint在哪的问题,也就是"Where is the endpoint?"

    B 解决的是如何与Endpoint通讯的问题,也就是"How to communicate with endpoint?"

    C解决了Endpoint提供什么功能的问题,也就是"What functionalities do the endpoint provide?"

    本文着重讨论Binding, Binding实现的是在客户端和服务端进行通讯的底层细节,包括数据如何传输(比如采用Tcp,Http等),如何解决安全问题 (SSL,Message Level Security等),传输的消息的格式(如text/xml,MTOM,binary等)。

    Binding的组成?

    Binding包括三个组成部 分:NameSpace,Name和BindingElement,如下图所示:

    Name和NameSpace是服务元数据(meta date)的唯一标志,换句话说,二者就像Binding的姓名一样,而BindingElement则描述Binding的特征,我们说Binding 能解决通讯方式的问题,关键是靠BindingElement来进行描述。

    Binding Element 的分类

    Binding Element中最核心的组成部分,它分为以下三种类型

    Encoding Binding Element:它用于描述传输数据的编码方式 ,比如用text/xml进行编码,用binary编码,用MTOM进行编码都是在这个上面定义,每个 Binding Element必须包含一个Encoding Binding Element。 三种编码方式的特点:纯文本(plain text)互操作能力好,二进制编码(binary encoding) 性能好,MTOM (Message Transport Optimization Mechanism) 负载能力好。
    Transport Binding Element:它用于描述数据的传输方式, 例如使用tcp进行传输,还是用http进行传输,还是用msmq,这些都是由Transport Binding Element来定
    义,每一个Binding Element 必须包含一个Transport Binding Element。

    Protocol Binding Element: 指定诸如安全性、可靠性、上下文流设置(context flow settings)


    Binding描述了哪些层面的信息

    一个Binding包含着丰富的信息,每种信息都描述了服务端和客户端交互过程中的一方面,如下表所示,Binding描述了这些层面的信息:

    层 次

    备 注说明

    Transactions(事 务)

    TransactionFlowBindingElement, 用于指定事务流程

    Reliability(信 赖)

    ReliableSessionBindingElement, 用于指定对会话方式

    Security(安 全)

    SecurityBindingElement, 指定安全方式

    Encoding(编 码)

    Text, Binary, MTOM, Custom,指定数据传输格式

    Transport(传 输)

    TCP, Named Pipes, HTTP, HTTPS, MSMQ, Custom,指定传输方式

    选择正确的 Binding

    Binding是可以自定义实现的,可WCF框架已经为我们实现了足够多的Binding,供我们来选择,如下表所示:

    Binding 名称

    Configuration Element

    描 述

    BasicHttpBinding

    basicHttpBinding

    一个指定用符合基本网络服务规范通讯的binding,它用http进行传输,数据格式为text/xml

    WSHttpBinding

    wsHttpBinding

    一个安全的通用的binding,但它不能在duplex中使用

    WSDualHttpBinding

    wsDualHttpBinding

    一个安全的通用的binding,但能在duplex中使用

    WSFederationHttpBinding

    wsFederationHttpBinding

    一个安全的通用的支持WSF的binding,能对用户进行验证和授权

    NetTcpBinding

    netTcpBinding

    在wcf应用程序中最适合跨机器进行安全通讯的binding

    NetNamedPipeBinding

    netNamedPipeBinding

    在wcf应用程序中最适合本机进行安全通讯的binding

    NetMsmqBinding

    netMsmqBinding

    在wcf应用程序中最适合跨机器进行安全通讯的binding,并且支持排队

    NetPeerTcpBinding

    netPeerTcpBinding

    一个支持安全的,多机交互的binding

    MsmqIntegrationBinding

    msmqIntegrationBinding

    一个用于wcf与现有msmq程序进行安全通讯的binding

    下面的表格分别删除了上表中的Binding在互操作性(Interoperability), 安全性(Security), 是否支持会话(Session), 是否支持事务(Transactions)和是否为全双工(Duplex)上不同。

    Bingding

    Interoperability

    Security

    Session

    Transactions

    Duplex

    BasicHttpBinding

    Basic Profile 1.1

    (None), Transport, Message

    None, (None)

    None

    n/a

    WSHttpBinding

    WS

    Transport, (Message), Mixed

    (None), Transport, Reliable Session

    (None), Yes

    n/a

    WSDualHttpBinding

    WS

    (Message)

    (Reliable Session)

    (None), Yes

    Yes

    WSFederationHttpBinding

    WS-Federation

    (Message)

    (None), Reliable Session

    (None), Yes

    No

    NetTcpBinding

    .NET

    (Transport), Message

    Reliable Session, (Transport)

    (None), Yes

    Yes

    NetNamedPipeBinding

    .NET

    (Transport)

    None, (Transport)

    (None), Yes

    Yes

    NetMsmqBinding

    .NET

    Message, (Transport), Both

    (None)

    (None), Yes

    No

    NetPeerTcpBinding

    Peer

    (Transport)

    (None)

    (None)

    Yes

    MsmqIntegrationBinding

    MSMQ

    (Transport)

    (None)

    (None), Yes

    n/a

    例外,《Programming WCF Services》有一幅图也能说明各自的特征:

    下面的图给出了我们选择Binding的 方式


    WCF 绑定(Binding)

    绑定包含多个绑定元素 ,它 们描述了所有绑定要求 。可以创建自定义绑定 ,也可以使用下表中的其中一个预定义绑定 :

    不同的绑定支持不同的功能。以Ws开头的绑定独立于平台 ,支持 Web服务规范。

    以 Net开 头的绑定使用二进制格式,使Net应用程序之间的通信有很高的性能。

    其他功能支持会话、可靠的会话、事务和双工通信。下表列出了支持这些功能的绑定 。

     

    Binding
     

    绑定可指定在与终结点通话时所使用的通信机制,并指示如何连接到终结点。

    绑定包含以下元素:

    协议堆栈确定用于发送到终结点的消息的安全性、可靠性和上下文流设置。

    传输确定将消息发送到终结点时使用的基础传输协议,例如 TCP 或 HTTP。

    编码确定用于发送到终结点的消息的网络编码,例如,文本/XML、二进制或消息传输优化机制 (MTOM)。
    具体的binding,功能不同,设置的属性不同,具体参照以下

    绑定 配置元素 说明
     BasicHttpBinding

     <basicHttpBinding>

    一个绑定,适用于与符合 WS-Basic Profile 的 Web 服务(例如基于 ASP.NET Web 服务 (ASMX) 的服务)进行的通信。此绑定使用 HTTP 作为传输协议,并使用文本/XML 作为默认的消息编码。

     WSHttpBinding

     <wsHttpBinding>

    一个安全且可互操作的绑定,适合于非双工服务约定。

     WSDualHttpBinding

     <wsDualHttpBinding>

    一个安全且可互操作的绑定,适用于双工服务协定或通过 SOAP 媒介进行的通信。

     WSFederationHttpBinding

     <wsFederationHttpBinding>

    一个支持 WS-Federation 协议的安全的、可互操作的绑定,使联盟中的组织可以高效地对用户进行身份验证和授权。

     NetTcpBinding

     <netTcpBinding>

    一个安全且经过优化的绑定,适用于 WCF 应用程序之间跨计算机的通信。

     NetNamedPipeBinding

     <netNamedPipeBinding>

    一个安全、可靠且经过优化的绑定,适用于 WCF 应用程序之间计算机上的通信。

     NetMsmqBinding

     <netMsmqBinding>

    一个排队绑定,适用于 WCF 应用程序之间的跨计算机的通信。

     NetPeerTcpBinding

     <netPeerTcpBinding>

    一个支持多计算机安全通信的绑定。

     MsmqIntegrationBinding

     <msmqIntegrationBinding>

    一个适合于 WCF 应用程序和现有消息队列应用程序之间的跨计算机通信的绑定。

     BasicHttpContextBinding

     <basicHttpContextBinding>

    一个绑定,适用于与符合 WS-Basic Profile 且允许使用 HTTP Cookie 交换上下文的 Web 服务进行的通信。

     NetTcpContextBinding

     <netTcpContextBinding>

    一个安全且经过优化的绑定,适用于允许使用 SOAP 标头交换上下文的 WCF 应用程序之间跨计算机的通信。

     WebHttpBinding

     <webHttpBinding>

    一个绑定,可用于为通过 HTTP 请求(而不是 SOAP 消息)公开的 WCF Web 服务配置终结点。

     WSHttpContextBinding

     <wsHttpContextBinding>

    一个安全且可互操作的绑定,适用于允许使用 SOAP 标头交换上下文的非双工服务协定。

    WCF Service Binding Explained

    This article offers a brief explanation on the basic concepts of the Communication part in the Windows Communication Foundation - WCF. To further illustrate the concepts, the article provides examples of configuration settings in the service's web.config file and the client code.

    In order to communicate with a WCF service, the client needs to know simple details like ABC of the service.

    The ABC of Windows Communication Foundation!!!

    Before we learn the ABC of WCF, we need to know how a WCF service is made accessible to the clients.

    A WCF service allows communication through an Endpoint. And the endpoint is the only point of communication of the WCF service that enables message exchange with the client as shown in Figure 1.

     And this Endpoint needs to set the ABC attributes of the WCF service as shown in Figure 2.

    An example of the Endpoint

    Let us quickly run through an example of an endpoint setting in the web.config file at the service side.

    <!-- Endpoint settings in WCF service -->
    < endpoint address = "  http://localhost:8731/EmployeeWCFService.ServiceImplementation.Manager/ "
    binding = "basicHttpBinding "
    contract = " EmployeeWCFService.ServiceContract.IEmployee " />

    Where, address is the network address of the service, binding specifies transport protocol (HTTP, TCP, etc.) selected for the service and contract is the interface the service implements.

    For the purpose of this article, we are going to emphasize on the Binding part of the WCF communication mechanism.

    So, what is the Binding?

    The Binding is an attribute of an endpoint and it lets you configure transport protocol, encoding and security requirements as shown in Figure 3

    How to setup the basicHttpBinding?

    Let us examine how to setup binding for an endpoint in the web.config file.

    Step 1: Choose basicHttpBinding as a value in the binding attribute of an endpoint.

    < endpoint
    address = "  http://localhost:8731/EmployeeWCFService.ServiceImplementation.Manager/ "
    binding = "basicHttpBinding " 
    bindingConfiguration = "basicBinding "
    contract = " EmployeeWCFService.ServiceContract.IEmployee ">

    Step 2: This step is optional and is only required if the binding's default properties need to be modified, as shown in the example below. In this case, name the binding same as bindingConfiguration attribute in the endpoint section.

    < bindings >|
    < basicHttpBinding >
                < binding    name = "basicBinding "
    textEncoding = "utf-8 "
    openTimeout = "00:03:00 "
    closeTimeout = "00:03:00 "
    />

    </ basicHttpBinding >          
    </ bindings >

    Note: All other types of binding are setup in the same way.

    wsHttpBinding

    This binding sends SOAP 1.2 messages and implements WS* specifications to support enterprise requirements of security, reliability, ordered delivery and transaction management.

    netTcpBinding

    This binding sends SOAP 1.2 messages, provides binary encoding and optimized communication between WCF services and WCF clients on Windows network. This binding is the fastest binding amongst all WCF binding options between different nodes in the TCP network. Unlike http bindings, the TCP binding does not offer interoperability but is highly optimized for .Net 3.0 and above clients. Thus, in .Net version 3.0 and above, providing an endpoint with netTcpBinding is an easy option to development of distributed systems and can replace COM+ and .Net Remoting model.

    Thumb rules in choosing endpoint' binding

    If you require your service to be consumed by clients compatible with SOAP 1.1, use basicHttpBinding for interoperability
    If you require your service to be consumed within the corporate network, use netTCPBinding for performance
    If you require your service to be consumed over the internet and the client is a WCF compatible, use wsHttpBinding to reap full benefits of WS* specifications
    If you require your service to be accessible only in the same machine, use netNamedPipeBinding
    If you require your service to be queue messages, use netMsmqBinding
    If you require your service to act as server as well as client in a peer to peer environment, utilise netPeerTcpBinding setting
    Binding configuration summary

    Following table shows parameters such as security, transport protocol, encoding and hosting environment choices available with different binding for a WCF service. This summary should help choose an appropriate binding for your project environment.


    Binding
    Security
    Default Configurable

    Transport Protocol Encoding
    Default Other Host
    basicHttpBinding
    None,
    Transport, Message, Mixed

    HTTP Text/XML, MTOM IIS, WAS
    wsHttpBinding Message, Transport, Mixed HTTP Text/XML, MTOM IIS, WAS
    netTcpBinding Transport, Message, Mixed TCP Binary WAS
    netNamedPipeBinding Transport, None Named Pipe Binary WAS
    netMsmqBinding Message, Transport, None TCP Binary WAS
    netPeerTcpBinding Transport P2P Binary -
    FAQ about an Endpoint

    Can I have multiple

    FAQ about an Endpoint
     
    Can I have multiple endpoints for a WCF service?
    Answer: Yes
     
    Can I have multiple endpoints of the same binding type e.g. multiple endpoints of basicHttpBinding?
    Answer: Yes
     
    Can I have multiple endpoints of different binding types to serve different types of clients e.g. an endpoint with basicHttpBinding, an endpoint with wsHttpBinding and an endpoint with netTcpBinging?
    Answer: Yes

    Summary

    As you have seen, Windows Communication Foundation provides a framework to configure the transport, security and encoding needs to cater various communication requirements. The WCF framework keeps the development API same irrespective of the way it is going to be consumed by the clients. And, the endpoint is provided to meet the communication requirements, and you can have one or many of them to cater to different clients and communication requirements. This eliminates the need to learn and implement diverse set of communication models to support HTTP or TCP communication infrastructures. 

    https://www.c-sharpcorner.com/uploadfile/pjthesedays/wcf-service-binding-explained/

    -----------------------------------
    WCF Service Binding Explained
    https://blog.51cto.com/u_15127571/3573295

    WCF配置Channel and Binding

    绑定无素定义了消息编码的协议,WCF提供了三种这类绑定元素:一种是将SOAP消息编码成文本,另一种是将SOAP编码成二

    进制格式;第三种是将SOAP消息根据SOAP MTOM(Message Transmission Optimization Mechanism,消息传输优化机

    制),MTOM编码适合那些包含大量二进制数据的SOAP消息.

    WCF的Binding模型之五:绑定元素(Binding Element)

    在上面的内容中,先后介绍了信道、信道管理器、信道监听器和信道工厂。从对象的创建来讲,信道管理器是信道的创建者。说的再具体点,客户端的信道通过信道工厂创建,服务端的信道通过信道监听器创建。但是信道工厂和信道监听器又是如果被创建出来的呢? 我们在一开始就已经说过,作为终结点三要素的绑定对象实现了所有的通信细节,并且通过创建信道栈实现了消息的传递。从这一点来说,绑定对象无疑是信道层所有通信对象的最终缔造者,所以信道工厂和信道监听器最终的创建都是靠绑定对象实现的。关于这个创建过程又和另一个重要的对象密切相关,那就是绑定元素。

    在上面的内容中,先后介绍了信道、信道管理器、信道监听器和信道工厂。从对象的创建来讲,信道管理器是信道的创建者。说的再具体点,客户端的信道通过信道工厂创建,服务端的信道通过信道监听器创建。但是信道工厂和信道监听器又是如果被创建出来的呢?

    我们在一开始就已经说过,作为终结点三要素的绑定对象实现了所有的通信细节,并且通过创建信道栈实现了消息的传递。从这一点来说,绑定对象无疑是信道层所有通信对象的最终缔造者,所以信道工厂和信道监听器最终的创建都是靠绑定对象实现的。关于这个创建过程又和另一个重要的对象密切相关,那就是绑定元素。

    绑定元素,顾名思义就是构成一个绑定对象的元素。绑定对象最根本的目的就是创建信道栈,借此实现对消息的传输、编码和基于消息交换的其他功能,比如安全、可靠传输、事务流转等等。组成信道栈的单个信道对象基于对某项单一功能的实现,在不同环境中,我们需要根据具体的需要创建相应的信道,并根据一定的顺序把这些信道组成一个完整的信道栈。对于绑定对象来说,如何实现这种灵活、自由的信道常创建方式,这得益于基于绑定元素的设计模式。

    三、 绑定揭秘

    前面我们一直在谈论信道、信道管理器、信道监听器、信道工厂和绑定元素,现在我们才进体本章的主题。不过由于前面的铺垫已经很足了,绑定本身反而没有太多可大书特书了。如果从结构上给绑定下个定义,那么我的定义很简单:“绑定是绑定元素的有序集合”。

    由于绑定的终极目标是实现对信道栈的创建,而对于一个信道栈来说,信道的构成和次序决定着该信道栈在最终消息通信中的特性与能力,而绑定元素有决定着信道的创建,所以绑定对象本身的特性与能力由构成它的所有绑定元素以及这些绑定元素之间的先后次序决定。

    正因为如此,当我们需要判断某一个绑定类型是否支持某种特性的时候,可以通过查看该绑定是否具有与此特性相关的绑定元素。比如,我们要判断某种绑定是否支持某种类型的传输协议,只需要看看构成该绑定的传输绑定元素就可以了,WsHttpBinding的传输绑定元素是HttpTransportBindingElement,所以 只能支持基于HTTP或者HTTPS的传输协议;如果需要确定某种类型的绑定是否支持事务的流转,只需要查看该绑定的绑定元素集合中是否包含TransactionFlowBindingElement就可以了。

    在WCF中,所有的绑定都直接或者间接继承自抽象基类:System.ServiceModel.Channels.Binding,我们现在来简单地分析一下这个基类。Binding实现了接口IDefaultCommunicationTimeouts。

    四个默认的超时时限可以通过编程的方式显式指定,也可以通过配置的方式进行设置。他们的默认值分别为:OpenTimeout、CloseTimeout和

    SendTimeout为1分钟,而ReceiveTimeout为10分钟。

    对于Binding,最为重要的就是如果构建组成该绑定对象的所有绑定元素集合。基于绑定元素的创建,通过抽象方法CreateBindingElements实现,所有具体的绑定类型均需要实现该方法。


    -----------------------------------
    WCF的Binding模型之五:绑定元素(Binding Element)
    https://blog.51cto.com/u_15127701/4759126

    WCF中的Binding模型之一: Binding模型简介

    一、 信道层与服务模型层(Channel Layer and Service Mode Layer)

    对于一个分布式应用的开发与设计来说,通信问题是不得不考虑,同时也是最为复杂、最难实现的问题。在过去的若干年中, 微软先后推出了一系列广受欢迎的通信技术, 比如DCOM、Enterprise Service、.NET Remoting、XML Web Service、MSMQ等等。这些技术提供了各自的编程模型,是开发人员从繁琐的完全基于通信的编程中解脱出来,使之仅仅需要关注具体的业务逻辑。WCF是所有的这些通信技术集大成者,它充分地整合了所有这些使用于不同领域、不同场景的通信技术,提供了一个统一的编程模型。

    无论从功能上讲,还是从WCF的整个基础构架的层次结构上讲,WCF可以分成两个不部分:编程模型和通信实现。编程模型通过WCF服务模型层(service mode layer)提供,而信道层 (channel layer) 则提供了具体的通信的实现。服务模型层建立在信道层之上,对于一般的WCF开发人员来讲,他们仅仅会接触到服务模型层,而信道层则是被屏蔽掉的。

    二、 信道与信道栈(Channel and Channel Stack)

    WCF的通信是基于消息的,如果从消息交换(message exchange)的角度讲,信道层则可以看成是进行消息交换参与者之间的中介。信道层通过一个个信道组成一个连续的信道栈,该信道栈构成了一个消息流通的管道。消息的发送者通过该管道流到消息的接收者,消息的接收者对消息进行相应的处理,生成新的消息通过该管道回复给消息的发送者。

    但是,不要将这个通过一系列信道组成的管道的功能仅仅局限于消息的传输,实际上该管道承载着许多额外的功能。

    我们可以打个比方,比如一个自来水厂,水源可能取自天然的湖水,在水厂生产的水最终通过自来水管流到居民的家中被饮用之前,需要对水进行必要的处理。中间的流程可能是这样的:湖水被汲取到一个池子中先进行杂质的过滤(我们称这个池为过滤池);被过滤后的水流到第二个池子中进行消毒处理(我们称这个池为消毒池);被消毒处理的后水流到第三个池子中进行水质软化处理(我们称这个池为软化池);最终水通过自来水管道流到居民的家中。

    实际上,我们将的信道栈就相当于一个自来水厂,而构成信道栈的一个个信道就相当过滤池、消毒池、软化池以及自来水管道。唯一不同的是,自来水厂处理的是水,而信道栈处理的是消息(message)。这样设计的最大的好处就是具有很强的可扩展性,因为我们不可能、也没有必要设计出一种信道能够进行所有的消息处理任务,我们需要做的仅仅让一个信道专注于某一种功能的实现,通过对信道的合理组合从而实现我们实际的消息处理的功能。

    对于一个自来水厂来说,最终的目的上自己生产的水让消费者能够饮用,所以自来水管道是必须的,至于中间的环节,过滤、消毒、软化、……,可能在水质良好的情况下就不是必要的了。与此类似,对于一个信道栈来说,有两种信道是必须的:传输信道(transport channel)和消息编码信道(message encoding channel)。原因很简单,信道栈的目的就是实现消息的传输,传输信道肯定是必须的,而进行传输的前提,需要对消息进行合理编码,比如基于文本编码和二进制编码。如下图所示:

    由于WCF采用完全基于消息的通信方式,所有功能的实现,无论是业务有关的,还是业务无关的,都是通过消息交换来实现的。对于信道栈来说,除了必要的消息处理功能(消息编码与传输),为了一些额外的功能的实现需要添加新的信道。比如,对于无状态的http协议需要提供对会话的支持,需要添加相应的会话支持的信道;为了通过对事物的支持,将多个服务调用纳入同一个事物中,需要专门的事物支持的信道;为了减少网络流量,在传输之前需要对消息进行压缩,需要专门的消息压缩信道,等等。

    从另一个方面讲,WCF是基于WS-*的,WS-*通过一系列的协议制定了一套业界的Web Service标准,使不同厂商之间的互操作成为可能。WCF对最新的WS-*提供了支持,而且毫无疑问,随着WS-*的逐步完善,WCF将会与之保持同步。对于绝大部分WS-*协议的支持,都是通过在信道栈中添加相应的信道实现的, 所以我们把这样的信道称为协议信道(protocol channel)。如下图所示,在传输信道和消息编码信道之上, WS-Security实现了消息层的安全;WS-RM(WS-Reliable Messaging)实现了可靠消息通信;WS-AT(WS-Atomic Transaction)实现了分布式的事务支持。

    三、 WCF的绑定模型(WCF Binding Mode)

    绑定模型如下图所示,其中最左边的部分就是信道栈,而右边就则是绑定对象本身。WCF通信的本质在于通过绑定对象提供的API构建信道栈,从而实现基于消息的通信。在信道栈和绑定之间,还存在着一些中间对象。它们是信道管理器(Channel Manager)、绑定元素(Binding Element)和绑定上下文(Binding Context)。

    在整个绑定模型中,信道和信道栈位于最底层。信道栈是消息进行通信的通道,组成信道栈的各个信道处于各自的目的对消息进行相应的处理。按照功能划分,可以将信道分成三类:传输信道、消息编码信道和协议信道。传输信道实现了基于某种协议(HTTP、HTTPS、TCP等等)的消息传输;消息编码实现了对消息的编码,常见的消息编码方式有:Text/XML、Binary和MTOM;而协议信道则实现了WCF对若然WS-*协议的支持,比如WS-Security、WS-RM、WS-AT等等。

    在WCF中,信道栈的创建和生命周期的管理通过信道管理器(channel manager)来进行管理。对于信道管理器,大家可能有点了陌生,不过如果回顾一下我们前面演示的通过绑定进行直接通信的例子,大家一定还记得这么两个对象:信道监听器(channel listener)和信道工厂(channel factory)。实际上,信道监听器和信道工厂是信道管理器两个别名。在服务端,通过信道监听器对服务请求进行监听,当请求消息被成功检测,则通过信道监听器创建信道栈对请求消息进行接收和处理;在客户端,信道栈被信道工厂创建,并用于请求消息的处理和发送。

    一般来讲,信道管理器,无论是信道监听器还是信道工厂,都对应着一个绑定元素(binding element)对象。绑定元素负责对相应信道管理器的创建。从创建对象的角度来看,信道管理器负责对信道的创建 ,而绑定元素则负责对信道管理器的创建。绑定元素,顾名思义,就是组成绑定的元素。从本质上讲,每一个绑定对象,就是一个绑定元素对象的有序集合;绑定元素的构成和次序决定绑定对象的特性。

    而我们所说的信道栈,指的是若干相关的信道按照一定的排列次序组成的一个消息流通的管道。信道栈中的信道的先后次序是如何来维护的呢?由于信道的创建者是信道管理器,所以信道管理者的次序决定信道的次序。从某种意义上讲,所有的信道管理器组成一个信道管理器栈。以此类推,信道管理器栈中每个信道管理器的先后次序由构成绑定对象的所有绑定元素的次序决定。但是绑定元素的次序先后次序又是如何决定的呢?那就需要使用到另一个有用的对象:绑定上下文(binding context)对象,一般来说,一个绑定上下文维护着基于该绑定对象当前绑定元素的有序列表,可以很容易地定位到下一个绑定元素。

    -----------------------------------
    WCF中的Binding模型之一: Binding模型简介
    https://blog.51cto.com/u_15077541/4758822

  • 相关阅读:
    day43——celery简介、celery小例子
    day42——queue模块
    day41——多进程的消息队列、消息队列pipe
    在风口浪尖后,如何有效控制权限?
    微服务架构下代码管理规范
    微服务架构下介质管理规范
    微服务架构下组件管理规范
    微服务架构下文档管理规范
    微服务与DevOps关系
    Springboot集成SpringData JPA
  • 原文地址:https://www.cnblogs.com/panpanwelcome/p/15803040.html
Copyright © 2020-2023  润新知