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

发布于 2024-07-30 03:22:26 字数 2614 浏览 9 评论 0原文

我正在尝试在 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 能够为我生成配置。

任何建议,将不胜感激。


异常的堆栈跟踪

服务器堆栈跟踪:  
     在 System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(消息回复、MessageFault 故障、字符串操作、MessageVersion 版本、FaultConverter 故障转换器) 
     在System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime操作,ProxyRpc&rpc) 
     在 System.ServiceModel.Channels.ServiceChannel.Call(字符串操作、布尔单向、ProxyOperationRuntime 操作、Object[] ins、Object[] outs、TimeSpan 超时) 
     在 System.ServiceModel.Channels.ServiceChannel.Call(字符串操作,布尔单向,ProxyOperationRuntime 操作,Object[] ins,Object[] outs) 
     在System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage方法调用,ProxyOperationRuntime操作) 
     在 System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage 消息) 
  

有一个内部异常(但不是在 Exeption.InnerExeption 下而是在 Exeption.Detail.InnerExeption 下 - ToString() 方法没有显示这一点)

URI“net.tcp://localhost:7771/MyService”的注册已存在。

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

I'm trying to communicate between WCF hosted in Windows Service and my service GUI. The problem is when I'm trying to execute OperationContract method I'm getting

"The ChannelDispatcher at
'net.tcp://localhost:7771/MyService'
with contract(s) '"IContract"' is
unable to open its IChannelListener."

My app.conf looks like that:

<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>

Port 7771 is listening (checked using netstat) and svcutil is able to generate configs for me.

Any suggestions would be appreciated.


Stack trace from exception

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)

There's one inner exeption (but not under Exeption.InnerExeption but under Exeption.Detail.InnerExeption - ToString() method doesn't show that)

A registration already exists for URI 'net.tcp://localhost:7771/MyService'.

But my service have specified this URI only in app.config file nowhere else. In entire solution this URI apears in server once and client once.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

绻影浮沉 2024-08-06 03:22:26

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

With this type of exception it's the Inner exception that has the information that is useful to diagnose the problem. This is a rather generic error that could be caused by a bunch of different things.

一身仙ぐ女味 2024-08-06 03:22:26

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

I solved it :D

Here's the explanaition of the problem:

First BAD code:

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
    }
}

As you can see the service contract is implemented in class hosting the service. This caused the whole error thing (maybe typeof() runs a constructor, i don't know I'm open to constructive input in this matter).

The GOOD code:

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
    }
}

Service Contract for both files:

[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>

葬シ愛 2024-08-06 03:22:26

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

I know you already solved the problem, but nobody pointed out why it solved the problem, and what caused the error. The issue w/ your first code was that your program (class Program) specified an open call to the class that was itself "class Program", in other words, it's RECURSIVE. No wonder it was giving the unable to open the listener error! This was a good one! :-)

樱花坊 2024-08-06 03:22:26

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

maybe the port is already used by another program on your machine, like an antivirus program? Or it's a Windows reserved port. Could you try setting the port to something like 11111?

一身软味 2024-08-06 03:22:26

我认为这部分配置

<message clientCredentialType="UserName" />

在设置时会被忽略

<security mode = "Transport">

I think this part of the configuration is ignored

<message clientCredentialType="UserName" />

when you set

<security mode = "Transport">
残疾 2024-08-06 03:22:26

我遇到此异常的原因与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
    }
}

I encountered this exception for the same reason as the OP but I couldn't move my service's implementation into a new class. So, I found another solution. ServiceHost has a second overload that takes an instance of a service. Thus, here are the changes applied to the OP's 'BAD' code:

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
    }
}
月光色 2024-08-06 03:22:26

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

There should be a host.Close() call before calling the service again. Therefore use try, catch and finally block. Close the connection in finally before making second call.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文