代码改变世界

WCF概述

2019-08-12 19:00  huoit  阅读(371)  评论(0)    收藏  举报

Tips:概念性的东西仅助理解,可以略过

概述

1、SOA概述

 

1)、从三个问题开始

SOA是什么——面向服务架构。一种编程模式、一种架构模式。它将应用程序分成不同功能(服务)单元,再通过服务之间的接口与契约联系起来,是一种松耦合架构

SOA的优势与好处——从组织分布式应用程序上讲SOA允许用户将不同的服务单元分布在不同的计算机上,客户端业务通过组织服务单元处理相应业务。安全上SOA的服务单元声明和签名对用户公开,而服务单元的具体实现是不可见的。

SOA什么时候用——从需求讲,当应用程序或系统越来越复杂庞大的时候就需要用一个严格且可大量重用维护性高的架构,同时要满足客户群体分散环境的互联。面向对象组件式的架构难以满足要求,这时候就要用SOA.SOA方式的架构中严格定义的接口需要可靠定义,实际开发中需求可能在变化,所以服务接口开发迭代中要明确变化和未变化的部分。

 

2、SOA底层

SOAP 简单对象协议,一种xml规范。有消息头和消息体

 

WS-* 协议

WCF中利用WSHttpBinding就可以实现WS-*协议,消息的寻址,发现,调用可靠性,了解

 

WSDL

1.WCF的命名空间

System.ServiceModel

2.WCF的ABC

Address:地址,服务地址在哪里;

Binding:服务绑定的协议,安全设置;

Contract:契约;服务的操作约定、消息描述等

3.WCF托管

控制台、应用程序、服务、Web

4.WCF操作重载

在服务接口的操作契约加上Name属性,取不同名字即可([OperationContract(Name = "SumA")])

5.WCF信息交互

请求响应、单工通信(即不需要响应)、双工通信(通常TCP协议)

6.安全模式

安全配置主要在Bind中,根据不同的绑定设置

1.传输安全
<netTcpBinding>
<binding name="netTcpTransportBinding">
   <security mode="Transport">
              <Transport clientCredentialType="Windows" />
   </security>
</binding>
</netTcpBinding>

2.消息安全
<wsHttpBinding>
<binding name="wsHttpMessageBinding">
  <security mode="Message">
              <Message clientCredentialType="UserName" />
  </security>
 </binding>
</wsHttpBinding>
3.
<basicHttpBinding>
<binding name="basicHttp">
  <security mode="TransportWithMessageCredential">
             <Transport />
                  <Message clientCredentialType="UserName" />
  </security>
</binding>
</basicHttpBinding>

 

7.生成代理

svcutil.exe /out:D:/a.cs /config:D:/a.config http://localhost:8012/ComputeService.svc?wsdl

 

双工通信

双工通讯客户端泛型

DuplexClientBase<IConpute> 正常请求响应默认ClientBase<IConpute>

 

1、契约C

    //设置回调
    [ServiceContract(CallbackContract = typeof(ICallBack))]
    public interface ICompute
    {
        [OperationContract(IsOneWay = true,Name = "AddDouble")]
        void Add(double x, double y);

        [OperationContract(IsOneWay = true,Name = "AddInt")]
        void Add(int x, int y);
    }
    //回调
    [ServiceContract]
    public interface ICallBack
    {
        [OperationContract(IsOneWay = true)]
        void Show(string result);
    }

 

2、服务端

1)service.svc.cs

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class ComputeService : ICompute
    {
        public void Add(double x, double y)
        {
            var result = x + y;
            ICallBack callBack = OperationContext.Current.GetCallbackChannel<ICallBack>();
            callBack.Show($"Double:{x}+{y}={result}");
        }

        public void Add(int x, int y)
        {
            var result = x + y;
            ICallBack callBack = OperationContext.Current.GetCallbackChannel<ICallBack>();
            callBack.Show($"INT:{x}+{y}={result}");
        }
    }

  

2)、服务端配置:configuration节点内

  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>

    <bindings>
      <netTcpBinding>
        <binding name="NetTcpBinding_ToolService" transferMode="Buffered" maxReceivedMessageSize="65536" portSharingEnabled="true">
          <security mode="None" />
        </binding>
      </netTcpBinding>
    </bindings>
    <services>
      <service name="Practice.Service.Web.ComputeService">
        <endpoint address="" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_ToolService" contract="Practice.Service.Contracts.ICompute" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
        <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
      </service>
    </services>
   
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>

 

3)宿主IIS,Web高级设置里>> 协议 >>添加net.tcp,其他的诸如绑好端口即可

 

3、生成代理

双工通信继承 DuplexClientBase<T>;也可以适用svcutil.exe /out:C:/xx.cs /config:C:/xx.config 

    public class ComputeClient : DuplexClientBase<ICompute>, ICompute
    {
        public ComputeClient(System.ServiceModel.InstanceContext callbackInstance) :
            base(callbackInstance)
        {
        }

        public ComputeClient(System.ServiceModel.InstanceContext callbackInstance, string endpointConfigurationName) :
            base(callbackInstance, endpointConfigurationName)
        {
        }

        public ComputeClient(System.ServiceModel.InstanceContext callbackInstance, string endpointConfigurationName, string remoteAddress) :
            base(callbackInstance, endpointConfigurationName, remoteAddress)
        {
        }

        public ComputeClient(System.ServiceModel.InstanceContext callbackInstance, string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
            base(callbackInstance, endpointConfigurationName, remoteAddress)
        {
        }

        public ComputeClient(System.ServiceModel.InstanceContext callbackInstance, System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
            base(callbackInstance, binding, remoteAddress)
        {
        }

        public void Add(double x, double y)
        {
            Channel.Add(x,y);
        }

        public void Add(int x, int y)
        {
            Channel.Add(x,y);
        }
    }

 

 

4、客户端

1)配置

<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
    </startup>
  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding name="Compute_Binding" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" transactionFlow="false" transactionProtocol="OleTransactions" maxBufferPoolSize="10485760" maxBufferSize="1310720" maxReceivedMessageSize="6553600">
          <security mode="None"/>
        </binding>
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint address="net.tcp://127.0.0.1:18012/ComputeService.svc" binding="netTcpBinding" bindingConfiguration="Compute_Binding" contract="Practice.Service.Contracts.ICompute" name="Compute_Endpoint"/>
    </client>
  </system.serviceModel>
</configuration>

 

2) program

    class Program
    {
        static void Main(string[] args)
        {
            //InstanceContext instanceContext = new InstanceContext(new CallbackImpl());
            //DuplexChannelFactory<ICompute> channelFactory =
            //    new DuplexChannelFactory<ICompute>(instanceContext, "Compute_Endpoint");
            //var proxy = channelFactory.CreateChannel();
            //using ( proxy as IDisposable)
            //{

            //    proxy.Add(2, 1);
            //}

            InstanceContext instanceContext = new InstanceContext(new CallbackImpl());
            using (var proxy=new ComputeClient(instanceContext))
            {
                proxy.Add(2, 1);
                //proxy.Add(1.0,2.0);//通信关闭
            }
            using (var proxy = new ComputeClient(instanceContext))
            {
                proxy.Add(1.0,2.0);
            }


            Console.ReadKey();
        }
    }

    [ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple)]
    public class CallbackImpl : ICallBack
    {
        public void Show(string result)
        {
            Console.WriteLine(result);
        }

    }