WCF 自托管

一、wcf托管服务的方式:

1):IIS5/6托管:与经典的webservice托管类似,把服务当成web项目,需要提供svc文件,其缺点是只能使用http协议,也就是说,只能使用单调服务,没有会话状态。IIS5还受端口的限制(所有服务必须使用相同的端口),主要优势是:客户端第一次请求是自动启动宿主进程。


2):was托管,全称windows激活服务,可托管网站,可托管服务,可使用任何协议,可以单独安装和配置,不依赖IIS7(一般情况在IIS7+中使用)。需要提供svc文件或在配置文件内提供等价的信息。


3):自托管,开发者提供和管理宿主进程生命周期的一种方法。可使用控制台程序,窗口程序,wpf程序提供宿主服务。可使用任意协议。必须先于客户端启动。可以实现wcf高级特性:服务总线,服务发现,单例服务。 


二、现在实现一个“控制台类型”的自托管服务(使用TCP协议),项目架构如下(下载项目):

                                                                                             WCF 自托管_第1张图片

1)定义服务接口文件代码:

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

namespace WcfService
{
    // 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”。
    [ServiceContract]
    public interface IMyService
    {

        [OperationContract]
        string GetData(int value);

        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);

        // TODO: 在此添加您的服务操作
    }


    // 使用下面示例中说明的数据约定将复合类型添加到服务操作。
    [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; }
        }
    }
}
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 WcfService
{
    //默认为会话服务
   [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
    public class MyService : IMyService
    {
        int InvokerCount = 0;

        public string GetData(int value)
        {
            InvokerCount++;
            return string.Format("CurrentInvokerCount:" + InvokerCount + "       You entered: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }
    }
}

3)main函数所在的程序入口文件代码(绑定NetTCP协议)(该功能也可以使用配置文件实现详情见附录A         也可以绑定Http协议,详情见附录B)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceModel;
using System.ServiceModel.Description;
using WcfService;

namespace WcfSelf
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Title = "WCF服务器端";

            /*定义ServiceHost对象,创建宿主
             * 参数1:实现契约的类
             * 参数2:为可选参数,Param类型的,定义了基址
             */
            using (ServiceHost host = new ServiceHost(typeof(MyService), new Uri("net.tcp://127.0.0.1:1212/sv")))
            {


                //使用Tcp协议
                NetTcpBinding binding = new NetTcpBinding();
                //安全性,一般为none
                binding.Security.Mode = SecurityMode.None;

                
                ServiceMetadataBehavior mb = new ServiceMetadataBehavior(); // 服务元数据
                mb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
                mb.HttpGetEnabled = true;                                   //是否可以查看元数据.此处可以false,那么HttpGetUrl就可以为空  
                mb.HttpGetUrl = new Uri("http://127.0.0.1:8008/meta");      //元数据的地址,HttpGetUrl 必须是相对 URI 或方案为“http”的绝对 URI。
                host.Description.Behaviors.Add(mb);                         //使用上面定义的Behaviors--服务元数据




                //endpoint: A:URI(相对与绝对的URI都行),需要与协议匹配,B:绑定的协议,C:实现契约的类型 
                host.AddServiceEndpoint(typeof(IMyService), binding, "");

                //指定用于通过 TCP 进行的 WS-MetadataExchange (WS-MEX) 消息交换的绑定的设置
                host.AddServiceEndpoint( ServiceMetadataBehavior.MexContractName,MetadataExchangeBindings.CreateMexTcpBinding(),"mex");//参数三不能为空或""



                //添加打开的匿名函数,没啥实际作用,就是提示
                host.Opened += (sender, arg) =>
                {
                    Console.WriteLine("服务已启动。");
                };
                try
                {
                    //打开服务
                    host.Open();
                   Console.Read();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }
    }
}



三、创建一个”客户端“控制台程序,用来测试调用服务

1)启动服务:运行服务程序生成的exe文件,提示如下图:



2)创建客户端控制台程序,添加服务引用:

WCF 自托管_第2张图片


3)主文件中main的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestClient
{
    class Program
    {
        static void Main(string[] args)
        {
            sr.MyServiceClient sc = new sr.MyServiceClient();
            Console.WriteLine( sc.GetData(212121));

            Console.WriteLine(sc.GetData(123123));

            Console.Read();
        }
    }
}
运行结果:

WCF 自托管_第3张图片


OK  完成!下载示例项目:下载


附录A:

使用配置文件来配置服务端:

  <system.serviceModel>
    <bindings>
      <!--绑定协议-->
      <netTcpBinding>
      </netTcpBinding>
    </bindings>
    <services>
      <!--name为实现契约的类  behaviorConfiguration为使用的behavior的name-->
      <service name="WcfCallBack.Service1" behaviorConfiguration="MyBehavior">
        <host>
          <baseAddresses>
            <!--如果是IIS+was托管,这个基地址无效,如果是自托管,该地址有用了-->
            <add baseAddress="net.tcp://127.0.0.1:1314/MyService" />
          </baseAddresses>
        </host>
        <!--终结点为空:使用IIS地址或基地址  契约:定义契约的类-->
        <endpoint address="" binding="netTcpBinding" contract="WcfCallBack.IService1" />
        <!--元数据访问地址:使用相对地址说明元数据地址为IIS地址或基地址加上“mex”拼接一起-->
        <!--例如 net.tcp://pc-20131208ieuv:2248/Service1.svc/mex,该地址也是非http类的协议添加服务引用的时候使用的地址-->
        <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <!--behavior的name-->
        <behavior name="MyBehavior">
          <!--无法获取元数据  强烈建议设为false-->
          <serviceMetadata httpGetEnabled="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>



附录B:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceModel;
using System.ServiceModel.Description;
using WcfService;

namespace WcfSelf
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Title = "WCF服务器端";

            /*定义ServiceHost对象,创建宿主
             * 参数1:实现契约的类
             * 参数2:为可选参数,Param类型的,定义了基址
             */
            using (ServiceHost host = new ServiceHost(typeof(MyService), new Uri("http://127.0.0.1:1212/sv")))
            {


                BasicHttpBinding binding = new BasicHttpBinding();   

                ServiceMetadataBehavior mb = new ServiceMetadataBehavior(); // 服务元数据
                mb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
                mb.HttpGetEnabled = true;                                   //是否可以查看元数据.此处可以false,那么HttpGetUrl就可以为空  
                mb.HttpGetUrl = new Uri("http://127.0.0.1:8008/meta");      //元数据的地址,HttpGetUrl 必须是相对 URI 或方案为“http”的绝对 URI。
                host.Description.Behaviors.Add(mb);                         //使用上面定义的Behaviors--服务元数据


                //endpoint: A:URI(相对与绝对的URI都行),需要与协议匹配,B:绑定的协议,C:实现契约的类型 
                host.AddServiceEndpoint(typeof(IMyService), binding, "");
                //指定用于通过 [TCP] 进行的 WS-MetadataExchange (WS-MEX) 消息交换的绑定的设置,如果是http,不能要写这一句
                //host.AddServiceEndpoint( ServiceMetadataBehavior.MexContractName,MetadataExchangeBindings.CreateMexTcpBinding(),"mex");



                //添加打开的匿名函数,没啥实际作用,就是提示
                host.Opened += (sender, arg) =>
                {
                    Console.WriteLine("服务已启动。");
                };
                try
                {
                    //打开服务
                    host.Open();
                   Console.Read();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }
    }
}




你可能感兴趣的:(WCF 自托管)