复习WCF(4)----- 承载服务

 

承载服务:

可以在IIS中承载,也可以在托管的应用程序中(自承载,自己承载自己),也可以在windows进程激活服务(WAS)中承载。(话说我现在也不知道WAS是啥,有空去了解下,但是可以知道它比IIS多支持一些协议)

 

一.IIS中承载

note:IIS5.1和IIS6.0仅限于HTTP通信,IIS7.0可以承载TCP/IP的协议还有命名管道以及MSMQ

如果要在IIS中承载,得安装和注册IIS和WCF以及WCF Http激活组件

IIS和WCF都很容易了,IIS就是在打开或关闭Windows功能里勾选安装,WCF在你装完VS2010就有了

WCF Http激活组件的话 也是在打开或关闭Windows功能里勾选安装 如图所示

 

接下来用一个内联例子演示 也就是直接在服务文件里面写上服务代码(.svc文件)

项目工程:

service.svc:

<%@ ServiceHost Language="c#" Debug="true" Service="Microsoft.ServiceModel.Samples.CalculatorService" %>


using System;
using System.ServiceModel;

namespace Microsoft.ServiceModel.Samples
{
    [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
    public interface ICalculator
    {
        [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);
    }

    public class CalculatorService : ICalculator
    {
        public double Add(double n1, double n2)
        {
            return n1 + n2;
        }

        public double Subtract(double n1, double n2)
        {
            return n1 - n2;
        }

        public double Multiply(double n1, double n2)
        {
            return n1 * n2;
        }

        public double Divide(double n1, double n2)
        {
            return n1 / n2;
        }
    }
}

这个例子其实和第二篇文章的例子差不多,分别就是加减乘除然后把结果返回给调用方 很简单

大家注意 因为如果在新建项里选择WCF服务,他生成的文件是有两个,还有一个IService1.cs的接口文件, 我不喜欢这样子 如图:

所以我一般建立svc文件,都是直接右键项目,选择新建项,然后选择文本文件  只是在名字那里写成了xxx.svc

当在svc里写代码的时候 刚写不会有只能提示,等你写完一个using System;之后,就会有智能提示了

 

web.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service
          name="Microsoft.ServiceModel.Samples.CalculatorService"
          behaviorConfiguration="CalculatorServiceBehavior">
        <!-- This endpoint is exposed at the base address provided by host: http://localhost/servicemodelsamples/service.svc  -->
        <endpoint address=""
                  binding="wsHttpBinding"
                  contract="Microsoft.ServiceModel.Samples.ICalculator" />
        <!-- the mex endpoint is exposed at http://localhost/servicemodelsamples/service.svc/mex -->
        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>

    <!--For debugging purposes set the includeExceptionDetailInFaults attribute to true-->
    <behaviors>
      <serviceBehaviors>
        <behavior name="CalculatorServiceBehavior">
          <serviceMetadata httpGetEnabled="True"/>
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>

</configuration>

大家可以在IIS管理器的"处理程序映射"中看到.svc ,如果没有看到.svc,那就证明开始的WCF Http组件激活是失败的

至此,服务已经完成(服务和配置文件),现在来将他部署到IIS上

部署上去也是非常简单的 就像我们部署asp.net应用程序一样 为了更加详细我就把所有步骤都传上来:

大功告成 现在来测试一下这个服务是否OK,测试方式就是在网页的URL上输入服务的网址

这个网址和平常的asp.net网址没什么区别,比如我的就是http://localhost/ServiceModelSamples/service.svc

你也可以在IIS管理器中选中刚才复制进去的service.svc文件,右键点击选择浏览,也会自动从浏览器中打开

如果没有问题 会出现这个画面:

大家可以看到第一行是 svcutil.exe http://teddy-pc/ServiceModelSamples/service.svc?wsdl

我们可以使用他来生成客户端的代理类和配置文件(当然,也可以在VS工程右键添加服务引用来生成) 现在 打开vs2010的命令提示工具

svcutil.exe:生成的命令 (如果对此命令好奇,可以直接敲此命令不加任何参数回车,他会展示出所有的参数和注释)

/out:cs代码生成路径 (例子中我放在了C盘根目录)

/config:配置文件生成路径 (例子中我放在了C盘根目录)

http://localhost/ServiceModelSamples/service.svc 开始部署在IIS中服务的路径

生成成功

 

现在我们来使用这个代理类 用控制台程序示例

将生成的文件copy到控制台程序里(这里可能会报错,因为客户端默认不会添加ServiceModel这个程序集,请手动添加)

然后给Main方法写上代码 来测试部署在IIS上的服务是否可行

    class Program
    {
        static void Main(string[] args)
        {
            //代理类
            CalculatorClient client = new CalculatorClient();
            
            double value1 = 100.00D;
            double value2 = 15.99D;
            double result = client.Add(value1, value2);
            Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);

            value1 = 145.00D;
            value2 = 76.54D;
            result = client.Subtract(value1, value2);
            Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);

            value1 = 9.00D;
            value2 = 81.25D;
            result = client.Multiply(value1, value2);
            Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);

            value1 = 22.00D;
            value2 = 7.00D;
            result = client.Divide(value1, value2);
            Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);

            client.Close();

            Console.WriteLine();
            Console.WriteLine("Press <ENTER> to terminate client.");
            Console.ReadLine();
        }
    }

好了 大功告成

 

 

二.在Windows进程激活服务(WAS) 中承载

和开始的IIS承载的步骤基本上一样,而且也是承载在IIS上,不同的是他可以支持Http和非Http协议(比如net.tcp)

这次我就不上图了  太麻烦 这文章也会显得很臃肿 具体步骤还是上面的例子 只是某些地方改下:

1.服务工程改为一个svc文件和cs文件,如service.cs和service.svc

   svc文件就指定一下,<%@ ServiceHost Language="c#" Debug="true" Service="Microsoft.ServiceModel.Samples.CalculatorService" %>

   cs文件就写上服务代码(服务协定和实现服务协定,也就是将上面的单个svc文件分为这两个文件)

   配置文件的绑定改为netTcpBinding,当然netTcpBinding这个绑定模式还得设置一下 所以用bindingConfiguration指定下设置 这里上传个代码:

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

    <services>
      <service name="Microsoft.ServiceModel.Samples.CalculatorService"
               behaviorConfiguration="CalculatorServiceBehavior">
        <!-- This endpoint is exposed at the base address provided by host: net.tcp://localhost/servicemodelsamples/service.svc  -->
        <endpoint binding="netTcpBinding" bindingConfiguration="PortSharingBinding"
          contract="Microsoft.ServiceModel.Samples.ICalculator" />
        <!-- the mex endpoint is exposed at net.tcp://localhost/servicemodelsamples/service.svc/mex -->
        <endpoint address="mex"
                  binding="mexTcpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>
    <bindings>
      <netTcpBinding>
        <binding name="PortSharingBinding"  portSharingEnabled="true">
          <security mode="None" />
        </binding>
      </netTcpBinding>
    </bindings>

    <!--For debugging purposes set the includeExceptionDetailInFaults attribute to true-->
    <behaviors>
      <serviceBehaviors>
        <behavior name="CalculatorServiceBehavior">
          <serviceMetadata />
          <serviceDebug includeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>
</configuration>

2.重新生成项目,将生成的bin文件夹和svc和config,copy到IIS上添加的应用程序对应的目录下。

3.选择此应用程序 选择高级设置,然后将“已启用的协议”加上net.tcp(如果还要别的协议就用逗号分隔) 如图

4.在生成代理类的时候 命令提示行代码基本一样 唯一不同的是更改服务地址的协议

比如以前是http://teddy-pc/ServiceModelSamples/service.svc   那现在就是net.tcp://teddy-pc/ServiceModelSamples/service.svc

你生成的配置文件中的服务地址也会自动为net.tcp

然后还是一样测试使用

注意:

IIS承载需要勾选红框的第一个

而这个承载需要勾选红框的第二个  反正你都勾了就好了

 

 

 

三.在托管应用程序中承载(自承载)

服务可以承载于任何.net framework应用程序中,自承载服务是最灵活的宿主选项,因为此服务部署所需要的基础结构最少

代码演示:

上面的服务都是wcf项目下建立的,而这个自承载就用应用程序项目,用控制台程序示例 首先创建一个控制台程序

服务端program.cs:

//  Copyright (c) Microsoft Corporation.  All Rights Reserved.

using System;
using System.Configuration;
using System.ServiceModel;

namespace Microsoft.ServiceModel.Samples
{
    [ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
    public interface ICalculator
    {
        [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);
    }

    //在服务里里面做了些简单的输出 以方便我们看到服务运转的情况
    public class CalculatorService : ICalculator
    {
        public double Add(double n1, double n2)
        {
            double result = n1 + n2;
            Console.WriteLine("服务端运行了!!加");
            return result;
        }

        public double Subtract(double n1, double n2)
        {
            double result = n1 - n2;
            Console.WriteLine("服务端运行了!!减");
            return result;
        }

        public double Multiply(double n1, double n2)
        {
            double result = n1 * n2;
            Console.WriteLine("服务端运行了!!乘");
            return result;
        }

        public double Divide(double n1, double n2)
        {
            double result = n1 / n2;
            Console.WriteLine("服务端运行了!! 除");
            return result;
        }

        //服务被“自承载”,就是从这里开始
        public static void Main()
        {
            //通过ServiceHost进行自承载
            using (ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService)))
            {
                //打开、侦听消息
                serviceHost.Open();

                //Open后就正常运转了
                Console.WriteLine("The service is ready.");
                Console.WriteLine("Press <ENTER> to terminate service.");
                Console.WriteLine();
                Console.ReadLine();

            }
        }

    }

}

 

App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service
          name="Microsoft.ServiceModel.Samples.CalculatorService"
          behaviorConfiguration="CalculatorServiceBehavior">
        <!--需要指定基址,因为它是自承载的,别人来访问服务,肯定需要一个地址吧-->
        <!--端口随便给,但是必须给,而且这个端口必须在计算机中已经打开,不然就访问不到-->
        <!--不要搞混了,这不是IIS!!!!-->
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8000/ServiceModelSamples11/service"/>
          </baseAddresses>
        </host>
        <endpoint address=""
                  binding="wsHttpBinding"
                  contract="Microsoft.ServiceModel.Samples.ICalculator" />
        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>

<behaviors> <serviceBehaviors> <behavior name="CalculatorServiceBehavior"> <serviceMetadata httpGetEnabled="True"/> <serviceDebug includeExceptionDetailInFaults="False" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel> </configuration>

打开8000端口:

现在这个自承载的服务就完成了

 

客户端和上面也一样 现在示例创建客户端

接下来我们下载元数据(也就是生成代理类)

在生成之前,你必须先把这个自承载的控制台程序先运行起来 不然就无法访问,所以请大家一定搞清楚,他并不是在IIS里~!!

运行起来后,你可以尝试将 http://localhost:8000/ServiceModelSamples11/service/mex输入在浏览器 但是没反应 所以更加确定它是和IIS无关的!!!

有人肯定会想为什么是http://localhost:8000/ServiceModelSamples11/service/mex  上面的例子不都是.svc结束吗

(因为上面都是将一个具体的服务文件xxx.svc承载在IIS里,而现在只是虚拟一下而已)

然后我们生成代理类,和上面一样用svcutil生成,但是注意 路径的最后面是/mex 其余的地方一模一样

后面的就一模一样了

将生成的文件copy到客户端,客户端还是那么几个方法,调用加减乘除,只是在调用的时候会输出结果

客户端Program.cs:

    class Program
    {
        static void Main(string[] args)
        {
            CalculatorClient client = new CalculatorClient();

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

            value1 = 145.00D;
            value2 = 76.54D;
            result = client.Subtract(value1, value2);
            Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);

            value1 = 9.00D;
            value2 = 81.25D;
            result = client.Multiply(value1, value2);
            Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);

            value1 = 22.00D;
            value2 = 7.00D;
            result = client.Divide(value1, value2);
            Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);

            client.Close();

            Console.WriteLine();
            Console.WriteLine("Press <ENTER> to terminate client.");
            Console.ReadLine();
        }
    }

然后可以测试了

因为不能在一个解决方案中同时运行两个程序,我们先把解决方案生成,然后将服务控制台程序设为启动项启动,然后在生成的客户端控制台程序目录双击运行

测试结果:

有兴趣的话,还可以在服务端的控制台程序代码里,设置一个断点自己研究研究

 

 

 

最后,我们来总结一下 承载方式有

1.IIS承载

2.在Windows进程激活服务(WAS) 中承载

3.在托管应用程序中承载(自承载

而1和2其实是差不多的,差不多的地方是都是通过IIS实现

但不同的地方是:虽然都是通过IIS,但IIS只是一个“入口”,最终会使用不同的辅助进程来完成承载

3的话呢,就更简单了,优点在与灵活

posted @ 2013-02-21 16:22  韬韬韬你羞得无礼  Views(210)  Comments(0)    收藏  举报