如何解决“ChannelDispatcher无法打开其IChannelListener”错误?

13

我正在尝试在Windows服务中托管的WCF与我的服务GUI之间进行通信。问题是当我尝试执行OperationContract方法时,我遇到了以下错误:

"The ChannelDispatcher at 'net.tcp://localhost:7771/MyService' with contract(s) '"IContract"' is unable to open its 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>

通过netstat检查,端口7771处于监听状态,并且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)

在异常信息中有一个内部异常(但不在Exception.InnerExeption下,而是在Exception.Detail.InnerExeption下 - ToString()方法不显示它)

已经为URI“net.tcp://localhost:7771/MyService”注册了一个注册表项。

但我的服务只在app.config文件中指定了这个URI,在整个解决方案中,此URI只出现一次于服务器和客户端各一次。


你能否使用 "theException.ToString()" 给我们提供完整的堆栈跟踪信息。这将显示所有内部异常。在这种类型的异常中,有时会存在另一个根本原因。 - Anderson Imes
7个回答

9

对于这种类型的异常,有用于诊断问题的信息位于内部异常中。这是一种相当通用的错误,可能由许多不同的原因引起。


5

我解决了 :D

以下是问题的解释:

第一段错误代码:

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>


5

我知道你已经解决了这个问题,但是没有人指出为什么它解决了问题以及什么导致了错误。你的第一段代码的问题在于,你的程序(类Program)指定了对其本身“类Program”的调用,换句话说,它是递归的。难怪它会给出“无法打开监听器”的错误!这是一个好问题! :-)


1

也许端口已经被你机器上的其他程序使用了,比如防病毒软件?或者是Windows保留端口。你可以尝试将端口设置为11111之类的数字。


不幸的是,它并不是。我尝试了不同的端口(7771、7772、7773)。在关闭我的服务后,端口从netstat输出中消失,所以可能没有其他东西在监听它们:/ - kyrisu

0

我认为这个配置的部分被忽略了

<message clientCredentialType="UserName" />

当你设置时

<security mode = "Transport">

0

我遇到了与操作者(OP)相同的异常,但是我无法将我的服务实现移动到一个新类中。因此,我找到了另一个解决方案。ServiceHost 有第二个重载,它接受一个服务实例。因此,这里是应用于操作者糟糕代码的更改:

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

在再次调用服务之前,应该有一个host.Close()的调用。因此,请使用try、catch和finally块。在finally中关闭连接后再进行第二次调用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接