2009-03-31 5 views
9

У меня возникла проблема. Я немного новичок в WCF, поэтому любая помощь будет очень восприимчивой.WCF: множественные привязки Net.TCP, один и тот же порт, разные IP-адреса

Вот мой код:

public static void StartHosts() 
    { 
     try 
     { 
      // Create a new host 
      ServiceHost host = new ServiceHost(typeof(ServerTasks)); 

      List<IPAddress> ips = new List<IPAddress>(Dns.GetHostAddresses(Dns.GetHostName())); 
      if (IPAddress.Loopback != null) 
       ips.Add(IPAddress.Loopback); 

      ips.RemoveAll(i => i.AddressFamily != AddressFamily.InterNetwork); 

      foreach (var ip in ips) 
      { 
       string uri = string.Empty; 

       // Formulate the uri for this host 
       uri = string.Format(
        "net.tcp://{0}:{1}/ServerTasks", 
        ip.ToString(), 
        ServerSettings.Instance.TCPListeningPort 
       ); 


       // Add the endpoint binding 
       host.AddServiceEndpoint(
        typeof(ServerTasks), 
        new NetTcpBinding(SecurityMode.Transport) { TransferMode = TransferMode.Streamed }, 
        uri 
       ); 

      } 



      // Add the meta data publishing 
      var smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>(); 
      if (smb == null) 
       smb = new ServiceMetadataBehavior(); 

      smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15; 
      host.Description.Behaviors.Add(smb); 

      host.AddServiceEndpoint(
       ServiceMetadataBehavior.MexContractName, 
       MetadataExchangeBindings.CreateMexTcpBinding(), 
       "net.tcp://localhost/ServerTasks/mex" 
      ); 

      // Run the host 
      host.Open(); 
     } 
     catch (Exception exc) 
     { 
      DebugLogger.WriteException(exc); 
     } 
    } 

Исключение брошено на линии: 'host.Open();'

Исключение:

System.InvalidOperationException Регистрационная уже существует для URI 'net.tcp: //192.168.1.45: 4329/ServerTasks'.

То, что я пытаюсь сделать, это привязка ко всем сетевым адресам на машине, чтобы клиентские приложения могли получить доступ к службе из любой сети, в которой они видны. Когда я запускаю этот код, он находит и пытается установить привязку для примерно 5 разных IP-адресов, включая 127.0.0.1.

192.168.1.45 - второй IP-адрес, к которому он пытается привязать. В тот момент, когда он генерирует исключение, я вижу (используя netstat), что программа привязана к первому IP в списке на порту 4329. Нет ничего связанного с портом 4329 по адресу, указанному в исключении.

Извините, у меня нет подробностей, я хотел бы дать краткий отчет. Если кому-то понадобится больше информации, я с удовольствием поставлю его.

Примечание. Я попытался настроить PortSharingEnabled на true для NetTcpBinding, которое создается внутри цикла foreach, но я все еще испытывал ту же ошибку.

Любая помощь или совет будет очень восприимчивой!

Благодаря

ответ

10

Спасибо за информацию CORAZZA!

Я выяснил, как это осуществить. Я все это делал неправильно.

Моя конечная цель состояла в том, чтобы служба прослушивала каждый IP-адрес, доступный на аппарате. Попытка связать с каждым адресом индивидуально - это неправильный способ сделать это.

Вместо этого мне нужно было связать службу только с машинным . Имя хоста (не «localhost»), а WCF автоматически прослушивает все адаптеры.

Вот исправленный код:

public static void StartHosts() 
    { 
     try 
     { 
      // Formulate the uri for this host 
      string uri = string.Format(
       "net.tcp://{0}:{1}/ServerTasks", 
       Dns.GetHostName(), 
       ServerSettings.Instance.TCPListeningPort 
      ); 

      // Create a new host 
      ServiceHost host = new ServiceHost(typeof(ServerTasks), new Uri(uri)); 

      // Add the endpoint binding 
      host.AddServiceEndpoint(
       typeof(ServerTasks), 
       new NetTcpBinding(SecurityMode.Transport) 
         { 
          TransferMode = TransferMode.Streamed 
         }, 
       uri 
      ); 

      // Add the meta data publishing 
      var smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>(); 
      if (smb == null) 
       smb = new ServiceMetadataBehavior(); 

      smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15; 
      host.Description.Behaviors.Add(smb); 

      host.AddServiceEndpoint(
       ServiceMetadataBehavior.MexContractName, 
       MetadataExchangeBindings.CreateMexTcpBinding(), 
       "net.tcp://localhost/ServerTasks/mex" 
      ); 

      // Run the host 
      host.Open(); 
     } 
     catch (Exception exc) 
     { 
      DebugLogger.WriteException(exc); 
     } 
    } 
+1

Привязка к каждому IP-адресу индивидуально - это правильно, потому что в противном случае у вашего сервера есть дыра в системе безопасности - представьте (маловероятная) ситуация, когда другая служба привязывается к определенному IP-адресу хоста и тому же порту, пока ваша служба привязана ко всем IP-адресам , В этом случае imposter получит все запросы на соединение от клиентов, отправляющихся на этот IP-адрес. – AlexT

2

Мел,

В то время как я никогда не пробовал это перед собой, вот некоторые образцы, чтобы смотреть на что я слышал раньше. Сначала вы можете создать свой объект привязки, а затем добавить один и тот же экземпляр в метод AddServiceEndpoint, просто подумайте, чтобы каждый раз, когда я не читал, где-то читал, что netTCPBindings должно быть отношением 1: 1 к адресу (хотя вы используете разные адреса).

Я не думаю, что вам нужно беспокоиться о совместном использовании портов, поскольку вы открываете несколько портов.

Вот пример того, что вы можете выполнить с несколькими портами.

http://www.aspfree.com/c/a/Windows-Scripting/WCF-and-Bindings/2/

Вот хороший пример для использования portsharing на NetTcpBinding.

http://blogs.msdn.com/drnick/archive/2006/08/08/690333.aspx

-Bryan

1

Похоже, я немного поздно :). Но в любом случае - есть довольно простой способ заставить Wcf прослушивать все доступные сетевые интерфейсы «net.tcp: //0.0.0.0: 8523/WCFTestService».