WCF: несколько привязок Net.TCP, один и тот же порт, разные IP-адреса - PullRequest
9 голосов
/ 01 апреля 2009

Я столкнулся с проблемой. Я немного новичок в WCF, поэтому любая помощь будет очень признательна.

Вот мой код:

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, но я все еще сталкивался с той же ошибкой.

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

Спасибо

Ответы [ 3 ]

10 голосов
/ 01 апреля 2009

Спасибо за информацию 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);
        }
    }
2 голосов
/ 01 апреля 2009

Мел,

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

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

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

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

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

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

-Bryan

1 голос
/ 11 марта 2016

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

...