C# WCF服务入门

前边在小卖部用的服务端是wcf写的,不过未有深切钻研,最近找工作,面试的时候好三个人探望那些总提问,那里做个复习

就用微软官方上的例子,搭三个简短的wcf服务,分6步

一定义服务协定也正是契约,其实正是概念3个劳动接口,那东西前面是公然客户端用的,然后也告知前边承载程序应该怎样加载服务

   主要涉嫌两天性状:二个是ServiceContract(接口的天性,定义那么些是劳务契约,里边又有的安装参数能够安装一下),OperationContract设置接口的格局的,假若不设置,方法就不会呗公开

  那里是直接新建的wcf的服务程序,vs自动给生成了2个接口,就径直在这些里面添加了多少个总括的接口函数了

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace GettingStartedLib
{

    // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”。
    //协定
    [ServiceContract(//CallbackContract =typeof(ICallBack),//双工时的返回协定
        ConfigurationName = "Calculator",//配置文件重的服务名
        Name = "ICalculator",//webservice描述文件重的portType名
        Namespace ="http://SampleWcfTest",//webservice描述文件重的portType命名空间
        ProtectionLevel =System.Net.Security.ProtectionLevel.EncryptAndSign,//保护等级
        SessionMode =SessionMode.Allowed)]//设置会话的支持模式
    public interface ICalculator
    {

        [OperationContract]
        string GetData(int value);

        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);
        //定义方法的操作,带了该特性才会被公布
        [OperationContract]
        double Add(double n1, double n2);
        [OperationContract]
        double Subtract(double n1, double n2);
        [OperationContract]
        double Multiply(double n1, double n2);
        [OperationContract]
        double Divide(double n1, double n2);

        // TODO: 在此添加您的服务操作
    }
    public interface ICallBack
    {
        [OperationContract(IsOneWay = true)]
        void Reply(string responseToGreeting);
    }

    // 使用下面示例中说明的数据约定将复合类型添加到服务操作。
    [DataContract]
    public class CompositeType
    {
        bool boolValue = true;
        string stringValue = "Hello ";

        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }

        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }
}

二完成上面包车型地铁接口,vs自动生成了svc文件和呼应的svc.cs文件,直接双击正是对应的实现类了,吧接口实现就好了,那个svc文件右键用文件编辑器打开药方可开始展览编辑,假使前面用IIS加载的时候须要修改里边的东西

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace GettingStartedLib
{
    // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“Service1”。
    // 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 Service1.svc 或 Service1.svc.cs,然后开始调试。
    public class Calculator : ICalculator
    {
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }
        public double Add(double n1, double n2)
        {
            double result = n1 + n2;
            Console.WriteLine("Received Add({0},{1})", n1, n2);
            // Code added to write output to the console window.
            Console.WriteLine("Return: {0}", result);
            return result;
        }

        public double Subtract(double n1, double n2)
        {
            double result = n1 - n2;
            Console.WriteLine("Received Subtract({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            return result;
        }

        public double Multiply(double n1, double n2)
        {
            double result = n1 * n2;
            Console.WriteLine("Received Multiply({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            return result;
        }

        public double Divide(double n1, double n2)
        {
            double result = n1 / n2;
            Console.WriteLine("Received Divide({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            return result;
        }
    }
}

3 承载服务,承载服务有三种方法,同时又安插到协和式飞机的绑定难题,

  绑定分类:BasicHttpBinding  最基础的http绑定,
        NetTcpbingding  TCP的  

        NetNamePipeBinding  IPC,也正是经过间通讯,没用过。。

        WSHttpBinding  那个是特种的http/Https协议 加了任陈峰西的

        NetMsmqBindiing,那几个是消息队列,笔者没用过,那玩意好像必要额外装微软的消息队列才能够用

  那里本人宗旨就用wshttpbinding来促成,

  承载方式:一)用控制台程序,直接用servicehost来承载服务,本人组织终结点:

            //服务的地址
            Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/");
            //承载服务的宿主
            ServiceHost selfHost = new ServiceHost(typeof(Calculator), baseAddress);

            try
            {
                selfHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "Calculator");
                ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
                smb.HttpGetEnabled = true;
                selfHost.Description.Behaviors.Add(smb);
                selfHost.Open();
                Console.WriteLine("The service is ready.");
                Console.WriteLine("input<exit> to terminate service.");
                Console.WriteLine();
                while ("exit" == Console.ReadLine())
                {
                    selfHost.Close();
                }
            }
            catch (CommunicationException ex)
            {
                Console.WriteLine(ex.Message);
                selfHost.Abort();
                Console.ReadLine();
            }

    二) 用IIS承载,这里又两种方式,通过internet的章程
这些能够间接在vs中调剂的,选中svc文件点调节和测试会弹出贰个wcf的客户端测试程序,能够直接实行测试,不过这一个客户端不能够测试异步,只好测同步

    那中艺术重点是亟需配备1个web.config文件,计划的话,间接在IIS添加网址服务程序,把变化的DLL和web.config放在一个索引下应该跟这么些调节和测试是一律的(这种方法IIS5
陆 只协助HTTP)

    还足以经过WAS(进度激活服务,协理的说道比下边多,这一个就平昔不尖锐斟酌了···)

<?xml version="1.0" encoding="utf-8"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5.2" />
    <httpRuntime targetFramework="4.5.2"/>
  </system.web>
  <system.serviceModel>
    <services>
      <service name="GettingStartedLib.Calculator" behaviorConfiguration="MyServiceTypeBehaviors" >
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8001/"/>
          </baseAddresses>
        </host>
        <endpoint address="CalculatorService" binding="wsHttpBinding" contract="Calculator">
        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyServiceTypeBehaviors" >
          <!-- 将下列元素添加到服务行为配置中。 -->
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
  <system.webServer>
    <!--<modules runAllManagedModulesForAllRequests="true"/>-->
    <!--
        若要在调试过程中浏览 Web 应用程序根目录,请将下面的值设置为 True。
        在部署之前将该值设置为 False 可避免泄露 Web 应用程序文件夹信息。
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>

</configuration>

  叁)通过windows服务程序承载,那么些里面开首也是servicehost来达成,只但是是挂在windows服务程序上,要求本人达成1个windows服务,也正是继承servicebase类,重写onstart,在onstart中用servicehost加载服务,在stop中停止服务,同时须要安顿文件便是先后的安插文件app.config记得生成到目录下,配置终结点。服务类生成的次第供给设置,还亟需持续install完毕3个设置类,把转变的服务程序安装到windows系统服务去,然后就能够在服务中运营服务,

其一装置是在总指挥权限下进入对应的.netframework目录下运作installutil
path(程序目录) 那里用的是四.5 ,正是v四.0。。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GettingStartedLib;
using System.ServiceModel.Description;
using System.ServiceModel;
using System.ServiceProcess;
using System.Configuration.Install;
using System.ComponentModel;

namespace WcfConsole
{
    public class serviceCalss : ServiceBase
    {
        public ServiceHost serviceHost = null;
        public serviceCalss()
        {
            ServiceName = "WCFWindowsServiceSample";

        }
        protected override void OnStart(string[] args)
        {
            if (serviceHost != null)
            {
                serviceHost.Close();
            }
            serviceHost = new ServiceHost(typeof(Calculator));

            serviceHost.Open();
        }

        protected override void OnStop()
        {
            if (serviceHost != null)
            {
                serviceHost.Close();
                serviceHost = null;
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {

            ServiceBase.Run(new serviceCalss());

            //服务的地址
            Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/");
            //承载服务的宿主
            ServiceHost selfHost = new ServiceHost(typeof(Calculator), baseAddress);

            //try
            //{
            //    selfHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "Calculator");
            //    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
            //    smb.HttpGetEnabled = true;
            //    selfHost.Description.Behaviors.Add(smb);
            //    selfHost.Open();
            //    Console.WriteLine("The service is ready.");
            //    Console.WriteLine("input<exit> to terminate service.");
            //    Console.WriteLine();
            //    while ("exit" == Console.ReadLine())
            //    {
            //        selfHost.Close();
            //    }
            //}
            //catch (CommunicationException ex)
            //{
            //    Console.WriteLine(ex.Message);
            //    selfHost.Abort();
            //    Console.ReadLine();
            //}
        }
    }

    [RunInstaller(true)]
    public class ProjectInstaller : Installer
    {
        private ServiceProcessInstaller process;
        private ServiceInstaller service;

        public ProjectInstaller()
        {
            process = new ServiceProcessInstaller();
            process.Account = ServiceAccount.LocalSystem;
            service = new ServiceInstaller();
            service.ServiceName = "WCFWindowsServiceSample";
            Installers.Add(process);
            Installers.Add(service);
        }
    }
}

对应的配备文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
    </startup>
  <system.serviceModel>
    <services>
      <!-- This section is optional with the new configuration model
           introduced in .NET Framework 4. -->
      <service name="GettingStartedLib.Calculator"
               behaviorConfiguration="CalculatorServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8000/"/>
          </baseAddresses>
        </host>
        <endpoint address=""
                  binding="wsHttpBinding"
                  contract="Calculator" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="CalculatorServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="False"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

四 服务端承载好了,就可以用客户端调用服务了,又二种方法

  客户端间接引用已经运转的劳动,vs会自动生成三个应和的client类,里边又设置好的劳务路径和接口之类的,也能够自个儿钦定路线,只用她的函数,记得close

           // CalculatorClient client = new CalculatorClient();
            var client = myChannelFactory.CreateChannel();


            double value1 = 100.00D;
            double value2 = 15.99D;
            double result = client.Add(value1, value2);
            Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);

  也足以用ChannelFactory<TChannel>类来组织1个client,那种格局是援引服务的契约接口,

     var myBinding = new WSHttpBinding();
            EndpointAddress myEndpoint = new EndpointAddress("http://localhost:8000/GettingStarted/");
            //EndpointAddress myEndpoint = new EndpointAddress("http://localhost:8000/"); 
            ChannelFactory<ICalculator> myChannelFactory = new ChannelFactory<ICalculator>(myBinding, myEndpoint);

  这里边都得以用配备文件来设置终结点,也正是绑定类型和地点,配置格局与服务端类似

伍,6就是布局和调用,那里就隐瞒了

此处只是简单的wcf实例,

实在还有内容尚未关联:

一不一致的绑定类型,怎么选用,网上有个图是判定哪些意况选拔相应的绑定类型,其实就是挑选情商

2加密,因为中间的次序用的是basichttpbingding正是正是主导的http绑定,客户端没用引用服务端,服务端以web服务的花样公开服务,客户端直接以http请求的款型来与服务端通讯,那样客户端cs和bs能够公用二个服务端,可是从未加密,传输的始末是全然领悟的··讲道理web服务那玩意本来就是发过去给人看的·公开应该也没啥好像····,面试的时候问到那一个题材一向懵逼了···那里临时没写
··那玩意好像挺麻烦的···

三那里在四.5的条件下编制的,服务公开之后会自动生成对应的异步执行办法,与事先的措施各异,在此以前是不合时宜的beginxxx的异步形式,重返1个Iasyncresult的结果,那里是四.5的async/await的情势来推行异步操作

4 wcf服务是足以包容asp.net
,也得以再次来到json格式的对象··这几个能够经过设置格局的操作天性能够设置

5wcf服务支撑双工,这么些就很流弊了,可是讲道理tcp这种本身就扶助双工,没实际商讨

6在双工情势下扶助回调,那几个意思好像是客户端请求达成再出发三个回调服务么···
没切磋···

。。。。。。

 

相关文章