Как решить ошибку «ChannelDispatcher не может открыть свой IChannelListener»? - PullRequest
10 голосов
/ 10 августа 2009

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

"ChannelDispatcher at 'Net.tcp: // локальный: 7771 / MyService' с контрактом (ами) невозможно открыть свой IChannelListener. "

Мой app.conf выглядит так:

<configuration>
<system.serviceModel>
    <bindings>
        <netTcpBinding>
            <binding name="netTcpBinding">
                <security>
                    <transport protectionLevel="EncryptAndSign" />
                </security>
            </binding>
        </netTcpBinding>
    </bindings>
    <behaviors>
        <serviceBehaviors>
            <behavior name="MyServiceBehavior">
                <serviceMetadata httpGetEnabled="true" httpGetUrl="http://localhost:7772/MyService" />
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <services>
        <service behaviorConfiguration="MyServiceBehavior"
            name="MyService.Service">
            <endpoint address="net.tcp://localhost:7771/MyService" binding="netTcpBinding"
                bindingConfiguration="netTcpBinding" name="netTcp" contract="MyService.IContract" />
        </service>
    </services>
</system.serviceModel>

Порт 7771 прослушивает (проверено с помощью netstat), и svcutil может генерировать для меня конфиги.

Любые предложения будут оценены.


Трассировка стека из исключения

Server stack trace: 
   at System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter)
   at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Есть одно внутреннее исключение (но не в Exeption.InnerExeption, а в Exeption.Detail.InnerExeption - метод ToString () этого не показывает)

Уже существует регистрация для URI 'net.tcp: // localhost: 7771 / MyService'.

Но мой сервис указал этот URI только в файле app.config, нигде больше. Во всем решении этот URI появляется на сервере один раз, а на клиенте один раз.

Ответы [ 7 ]

7 голосов
/ 08 апреля 2010

С этим типом исключения именно внутреннее исключение содержит информацию, которая полезна для диагностики проблемы. Это довольно общая ошибка, которая может быть вызвана множеством разных вещей.

5 голосов
/ 10 августа 2009

Я решил это: D

Вот объяснение проблемы:

Первый код BAD:

namespace WCFServer
{
    public class Program : IWCFService
    {
        private ServiceHost host;

        static void Main(string[] args)
        {
            new Program();
        }

        public Program()
        {
            host = new ServiceHost(typeof(Program));

            host.Open();

            Console.WriteLine("Server Started!");

            Console.ReadKey();
        }

        #region IWCFService Members

        public int CheckHealth(int id)
        {
            return (1);
        }

        #endregion
    }
}

Как видите сервисный контракт реализован в классе хостинга сервиса. Это вызвало всю ошибку (возможно, typeof () запускает конструктор, я не знаю, что я открыт для конструктивного ввода в этом вопросе).

ХОРОШИЙ код:

namespace WCFServer
{
    public class Program
    {
        private ServiceHost host;

        static void Main(string[] args)
        {
            new Program();
        }

        public Program()
        {
            host = new ServiceHost(typeof(WCF));

            host.Open();

            Console.WriteLine("Server Started!");

            Console.ReadKey();
        }
    }

    public class WCF : IWCFService
    {

        #region IWCFService Members

        public int CheckHealth(int id)
        {
            return (1);
        }

        #endregion
    }
}

Договор на обслуживание обоих файлов:

[ServiceContract]
public interface IWCFService
{
    [OperationContract]
    int CheckHealth(int id);
}

App.config

<configuration>
<system.serviceModel>
    <behaviors>
        <serviceBehaviors>
            <behavior name="WCFBehavior" />
        </serviceBehaviors>
    </behaviors>
    <bindings>
        <netTcpBinding>
            <binding name="tcpBinding">
                <security>
                    <transport>
                        <extendedProtectionPolicy policyEnforcement="Never" />
                    </transport>
                </security>
            </binding>
        </netTcpBinding>
    </bindings>
    <services>
        <service name="WCFServer.WCF">
            <endpoint address="net.tcp://localhost:1111/TcpIHostMonitor" binding="netTcpBinding"
                bindingConfiguration="tcpBinding" name="netTcpEndpoint" contract="WCFServer.IWCFService" />
        </service>
    </services>
</system.serviceModel>

4 голосов
/ 12 сентября 2016

Я знаю, что вы уже решили проблему, но никто не указал, почему это решило проблему и что вызвало ошибку. Проблема с вашим первым кодом заключалась в том, что ваша программа (класс Program) указала открытый вызов для класса, который сам был «классом Program», другими словами, он RECURSIVE. Не удивительно, что это дало неспособность открыть ошибку слушателя! Это был хороший! : -)

1 голос
/ 10 августа 2009

может, порт уже используется другой программой на вашем компьютере, например антивирусной программой? Или это зарезервированный порт Windows. Не могли бы вы попытаться настроить порт на что-то вроде 11111?

0 голосов
/ 04 апреля 2018

Перед повторным вызовом службы должен быть host.Close() звонок. Поэтому используйте try, catch и, наконец, block. Наконец, завершите соединение перед вторым вызовом.

0 голосов
/ 04 сентября 2014

Я столкнулся с этим исключением по той же причине, что и OP, но не смог перенести реализацию моего сервиса в новый класс. Итак, я нашел другое решение. ServiceHost имеет вторую перегрузку, которая принимает экземпляр службы. Таким образом, вот изменения, примененные к коду BAD ОП:

namespace WCFServer
{
    [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)] // required
    public class Program : IWCFService
    {
        private ServiceHost host;

        static void Main(string[] args)
        {
            new Program();
        }

        public Program()
        {
            host = new ServiceHost(this); // changed
            host.Open();

            Console.WriteLine("Server Started!");
            Console.ReadKey();
        }

        #region IWCFService Members

        public int CheckHealth(int id)
        {
            return (1);
        }

        #endregion
    }
}
0 голосов
/ 11 ноября 2010

Я думаю, что эта часть конфигурации игнорируется

<message clientCredentialType="UserName" />

при установке

<security mode = "Transport">
...