引用 WCF 本质(3)

 

引用

wxfclniceWCF 本质(3)

6. 端点 (Endpoints)

每个服务都会关联到一个用于定位服务位置的地址(Address),一个用于定义如何与服务进行通讯的绑定(Binding),以及一个告知客户端服务能做什么的契约(Contract),这三样共同组成了服务的助记符 —— ABC。WCF 以端点(Endpoint)这样一个形式来体现三者的关系,端点本身就是地址、契约和绑定的组合体。

WCF 本质(3) - wxfclnice - 逍遥彩上飞的博客

端点示意图

每个端点都必须完整拥有这三个组成部分,宿主(host)则通过公开端点来对外提供服务。理论上,端点就是服务的外部交互接口、就像 CLR 或者 COM 接口。每个服务至少需要公开一个端点,服务上所有的端点都必须拥有唯一的定位地址,单个服务可以提供多个端点供不同类型的客户端调用。这些端点可以使用相同或不同的绑定对象,可以拥有相同或不同的服务契约。单个服务的不同端点之间没有任何关联。

端点配置管理

我们可以在宿主配置文件(app.config / web.config)中对端点参数进行设置。

<system.serviceModel>

   <services>

     <service name = "MyNamespace.MyService">

       <endpoint

         address = "http://localhost:8000/MyService/"

         binding = "wsHttpBinding"

         contract = "MyNamespace.IMyContract"

       />

     </service>

   </services>

</system.serviceModel>

需要注意的是,我们必须指定完整的契约限定名(含 Namespace)。当然,我们可以为单个服务提供多个端点设置。

<service name = "MyService">

   <endpoint

     address = "http://localhost:8000/MyService/"

     binding = "wsHttpBinding"

     contract = "IMyContract"

   />

   <endpoint

     address = "net.tcp://localhost:8001/MyService/"

     binding = "netTcpBinding"

     contract = "IMyContract"

   />

   <endpoint

     address = "net.tcp://localhost:8002/MyService/"

     binding = "netTcpBinding"

     contract = "IMyOtherContract"

   />

</service>

在配置文件中设置服务参数是种非常好的选择,它提供了更好的弹性,可以在不修改代码不重新发布系统的情况下对服务的地址、绑定和契约参数进行修改。

我们还可以提供一个或多个默认的基本地址(Base Address),这样在端点设置中只需提供相对地址。多个基本地址之间不能冲突,不能在同一个端口进行监听。相对地址通过端点绑定类型与基本地址进行匹配,从而在运行时获得完整地址。如果我们将某个端点设置中的地址设为空值(或省略 address),则表示直接使用某个相匹配的基本地址。

<service name = "MyService">

   <host>

     <baseAddresses>

       <add baseAddress="http://localhost:8080/" />

       <add baseAddress="net.tcp://localhost:8081/" />

     </baseAddresses>

</host>

<endpoint

     address = "MyService" <!-- http://localhost:8080/MyService -->

     binding = "wsHttpBinding"

     contract = "IMyContract"

   />

   <endpoint

     address = "MyService" <!-- net.tcp://localhost:8081/MyService -->

     binding = "netTcpBinding"

     contract = "IMyContract"

   />

   <endpoint

     address = "net.tcp://localhost:8002/MyService/"

     binding = "netTcpBinding"

     contract = "IMyOtherContract"

   />

</service>

我们还可以进一步对端点中的绑定参数进行设置。每种绑定类型可拥有多个名称(name)不同的参数设置,然后在端点的 bindingConfiguration 属性中指定关联设置名称即可。

<system.serviceModel>

   <services>

     <service name = "MyService">

       <endpoint

         address = "net.tcp://localhost:8000/MyService/"

         bindingConfiguration = "TransactionalTCP"

         binding = "netTcpBinding"

         contract = "IMyContract"

       />

     </service>

   </services>

   <bindings>

     <netTcpBinding>

       <binding name = "TransactionalTCP"

         transactionFlow = "true"

       />

     </netTcpBinding>

   </bindings>

</system.serviceModel>

下面是一个完整的演示。

[ServiceContract]

interface IMyService

{

   [OperationContract]

   void Test(int x);

}

class MyService : IMyService

{

   public void Test(int x)

   {

     Console.WriteLine(x);

   }

}

class Program

{

   static void Main(string[] args)

   {

     var host = new ServiceHost(typeof(MyService));

     host.Open();

     // ------------

    

     var http = ChannelFactory<IMyService>.CreateChannel(new BasicHttpBinding(),

       new EndpointAddress("http://localhost:801/MyService"));

      

     using (http as IDisposable)

     {

       http.Test(1);

     }

     // ----------------

    

     var tcp = ChannelFactory<IMyService>.CreateChannel(new NetTcpBinding(),

       new EndpointAddress("net.tcp://localhost:802/MyService"));

      

     using (tcp as IDisposable)

     {

       tcp.Test(1);

     }

     Console.WriteLine("Press any key to exit...");

     Console.ReadKey(true);

     Environment.Exit(0);

   }

}

App.config

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

<configuration>

   <system.serviceModel>

     <services>

       <service name="Learn.CUI.MyService">

         <host>

           <baseAddresses>

             <add baseAddress="http://localhost:801" />

             <add baseAddress="net.tcp://localhost:802" />

           </baseAddresses>

         </host>

         <endpoint

           address="MyService"

           binding="basicHttpBinding"

           contract="Learn.CUI.IMyService"

         />

         <endpoint

           address="MyService"

           binding="netTcpBinding"

           contract="Learn.CUI.IMyService"

         />

       </service>

     </services>

   </system.serviceModel>

</configuration>

除了使用配置文件外,我们还可以直接在代码中对端点参数进行设置。

ServiceHost host = new ServiceHost(typeof(MyService));

Binding wsBinding = new WSHttpBinding( );

Binding tcpBinding = new NetTcpBinding( );

host.AddServiceEndpoint(typeof(IMyContract), wsBinding, "http://localhost:8000/MyService");

host.AddServiceEndpoint(typeof(IMyContract), tcpBinding, "net.tcp://localhost:8001/MyService");

host.AddServiceEndpoint(typeof(IMyOtherContract), tcpBinding, "net.tcp://localhost:8002/MyService");

host.Open( );

ServiceHost 类型用来创建 Self-Hosting,AddServiceEndpoint(...) 有多个重载方法,用于添加端点设置。

和上面配置文件中所做的一样,在代码里同样可以使用绝对或相对地址。

Uri baseHttpUri = new Uri("http://localhost:8000");

Uri baseTcpUri = new Uri("net.tcp://localhost:8001");

ServiceHost host = new ServiceHost(typeof(MyService), baseHttpUri, baseTcpUri);

Binding wsBinding = new WSHttpBinding( );

Binding tcpBinding = new NetTcpBinding( );

host.AddServiceEndpoint(typeof(IMyContract), wsBinding, "MyService");

host.AddServiceEndpoint(typeof(IMyContract), tcpBinding, "MyService");

host.AddServiceEndpoint(typeof(IMyOtherContract), tcpBinding, "net.tcp://localhost:8002/MyService");

host.Open( );

至于绑定类型的设置,同样没啥问题。

ServiceHost host = new ServiceHost(typeof(MyService));

NetTcpBinding tcpBinding = new NetTcpBinding( );

tcpBinding.TransactionFlow = true;

host.AddServiceEndpoint(typeof(IMyContract), tcpBinding, "net.tcp://localhost:8000/MyService");

host.Open( );

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值