【问题标题】:How to solve "The ChannelDispatcher is unable to open its IChannelListener" error?如何解决“ChannelDispatcher 无法打开其 IChannelListener”错误?
【发布时间】:2010-11-18 04:14:02
【问题描述】:

我正在尝试在 Windows 服务中托管的 WCF 和我的服务 GUI 之间进行通信。问题是当我尝试执行我得到的 OperationContract 方法时

“ChannelDispatcher 在 'net.tcp://localhost:7771/MyService' 与合同 '"IContract"' 是 无法打开其 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' 的注册已经存在。

但是我的服务只在 app.config 文件中指定了这个 URI,没有其他地方。在整个解决方案中,此 URI 在服务器中出现一次,在客户端中出现一次。

【问题讨论】:

  • 您能否使用“theException.ToString()”给我们一个完整的堆栈跟踪。这将显示所有内部异常。除了这种异常,有时还有另一个根本原因。

标签: c# wcf interprocess net.tcp


【解决方案1】:

对于这种类型的异常,内部异常具有对诊断问题有用的信息。这是一个相当普遍的错误,可能由很多不同的事情引起。

【讨论】:

    【解决方案2】:

    我解决了: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>
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        【解决方案4】:

        也许该端口已被您机器上的另一个程序(如防病毒程序)使用?或者它是一个 Windows 保留端口。您可以尝试将端口设置为 11111 之类的吗?

        【讨论】:

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

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

        <message clientCredentialType="UserName" />
        

        当你设置时

        <security mode = "Transport">
        

        【讨论】:

          【解决方案6】:

          我遇到此异常的原因与 OP 相同,但我无法将我的服务实现移动到新类中。所以,我找到了另一个解决方案。 ServiceHost 有第二个重载,它接受一个服务的实例。因此,以下是应用于 OP 的“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
              }
          }
          

          【讨论】:

            【解决方案7】:

            在再次调用服务之前应该有一个host.Close() 调用。因此使用 try、catch 和 finally 块。在最后一次调用之前关闭连接。

            【讨论】:

              猜你喜欢
              • 2020-03-26
              • 2021-07-31
              • 2016-11-06
              • 2011-10-27
              • 2012-01-10
              • 1970-01-01
              • 1970-01-01
              • 2021-10-04
              • 1970-01-01
              相关资源
              最近更新 更多