WCF-ServiceEndpoint的监听地址与监听模式

  ServiceEndpoint具有一个可读可写的ListenUri属性,该属性表示服务端终结点的物理监听地址,该地址默认和终结点逻辑地址一致(即ServiceEndpoint的Uri)。对于客户端来说,请求真正发送的目标地址是服务的监听地址,默认情况下终结点的逻辑地址和监听地址是一样的。监听地址可以通过ServiceHost的AddServiceEndpoint指定。

public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address);
public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address);
public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address, Uri listenUri);
public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address, Uri listenUri);

 在实际的运行中,ServiceEndpoint的最终监听地址还要由ListenUriMode一起控制。ListenUriModel定义如下:

public enum ListenUriMode
{
  Explicit = 0,
  Unique = 1,
}

  Explicit表示终结点的监听地址严格采用ListenUri指定设置的Uri,Unique会根据终结点采用的策略确定最终使用的监听地址。

在采用Unique的情况下,监听器地址的生成策略如下:

  1.采用Tcp协议并且不采用端口共享,会选择一个未使用的端口作为保证监听地址的唯一性。

  2.采用Tcp协议并且采用端口共享,会在原有的监听地址后面加一个Guid以保证监听地址的唯一性。

  3.采用非Tcp协议,会在原有的监听地址后面加一个Guid以保证监听地址的唯一性。

下面代码演示服务端是如何确定终结点的监听地址,监听地址在信道分发器(ChannelDispatcher)中体现,

using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
namespace host
{
    class Program
    {
        static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(typeof(mywcf.Calculator)))
            {
                ServiceEndpoint endpoint1 = host.AddServiceEndpoint(typeof(mywcf.ICalculator), new WSHttpBinding(), "http://localhost:1111");

                ServiceEndpoint endpoint2 = host.AddServiceEndpoint(typeof(mywcf.ICalculator), new WSHttpBinding(), "http://localhost:2222");
                endpoint2.ListenUriMode = ListenUriMode.Unique;

                ServiceEndpoint endpoint3 = host.AddServiceEndpoint(typeof(mywcf.ICalculator), new NetTcpBinding(), "net.tcp://localhost:3333");
                endpoint3.ListenUriMode = ListenUriMode.Unique;

                NetTcpBinding tcpbind = new NetTcpBinding();
                tcpbind.PortSharingEnabled = true;
                ServiceEndpoint endpoint4 = host.AddServiceEndpoint(typeof(mywcf.ICalculator), tcpbind, "net.tcp://localhost:4444");
                endpoint4.ListenUriMode = ListenUriMode.Unique;

                ServiceEndpoint endpoint5 = host.AddServiceEndpoint(typeof(mywcf.ICalculator), new NetTcpBinding(), "net.tcp://localhost:5555");
                host.Opened += delegate { Console.WriteLine("Service Start!"); };
                host.Open();

                foreach (var dispatch in host.ChannelDispatchers)
                {
                    Console.WriteLine(dispatch.Listener.Uri);
                }
            }
        }
    }
}

 输出:

endpoint1的监听地址采用默认值,与逻辑地址一致。endpoint2使用了Unique模式,并且是非tcp协议类型,在默认的前提下添加一个GUID。endpoint3使用了Unique模式,并且是tcp协议类型,运行是分配了一个没有被使用的端口。endpoint4采用了端口共享模式,并且是tcp协议类型,监听地址加一个GUID。endpoint5监听地址默认与逻辑地址一致。

示例代码也可以用配置文件方式演示,配置文件如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <netTcpBinding>
        <binding portSharingEnabled="True" name="tcpbind"></binding>
      </netTcpBinding>
    </bindings>
    <services>
      <service name="mywcf.Calculator">
        <endpoint contract="mywcf.ICalculator" binding="wsHttpBinding" address="http://localhost:1111"></endpoint>
        <endpoint contract="mywcf.ICalculator" binding="wsHttpBinding" address="http://localhost:2222" listenUriMode="Unique"></endpoint>
        <endpoint contract="mywcf.ICalculator" binding="netTcpBinding" address="net.tcp://localhost:3333" ></endpoint>
        <endpoint contract="mywcf.ICalculator" binding="netTcpBinding" address="net.tcp://localhost:4444" listenUriMode="Unique"></endpoint>
        <endpoint contract="mywcf.ICalculator" binding="netTcpBinding" bindingConfiguration="tcpbind" address="net.tcp://localhost:5555" listenUriMode="Unique" ></endpoint>
      </service>
    </services>
  </system.serviceModel>
</configuration>

 采用了配置文件后服务端代码就很简单了,如下:

using System.ServiceModel;
namespace hostxml
{
    class Program
    {
        static void Main(string[] args)
        {
            using (ServiceHost host = new ServiceHost(typeof(mywcf.Calculator)))
            {
                host.Opened += delegate { Console.WriteLine("Service Start!"); };
                host.Open();
                foreach (var dispatch in host.ChannelDispatchers)
                {
                    Console.WriteLine(dispatch.Listener.Uri);
                }
            }
        }
    }
}

 

posted @ 2015-03-30 21:54  lh_cn  阅读(2026)  评论(0编辑  收藏  举报