通信对象System.ServiceModel.Channels.ServiceChannel不能用于通信

问题描述 投票:138回答:14

通信对象System.ServiceModel.Channels.ServiceChannel不能用于通信,因为它处于Faulted状态。

什么是这个错误,我将如何解决它?

c# wcf
14个回答
135
投票

您收到此错误是因为您在服务器端发生了.NET异常,并且您没有捕获并处理它,也没有将其转换为SOAP错误。

现在,由于服务器端“被轰炸”,WCF运行时已“故障”通道 - 例如客户端和服务器之间的通信链接是不可用的 - 毕竟,它看起来像你的服务器爆炸,所以你不能再与它通信。

所以你需要做的是:

  • 始终捕获并处理服务器端错误 - 不要让.NET异常从服务器传递到客户端 - 始终将这些错误包装成可互操作的SOAP错误。查看WCF IErrorHandler接口并在服务器端实现它
  • 如果您要从客户端向您的频道发送第二条消息,请确保该频道未处于故障状态: if(client.InnerChannel.State != System.ServiceModel.CommunicationState.Faulted) { // call service - everything's fine } else { // channel faulted - re-create your client and then try again } 如果是,您所能做的只是处理它并再次重新创建客户端代理,然后再试一次

0
投票

在我的情况下,原因是一些无法加载的错误证书。我从系统中的事件查看器中发现了它:

尝试访问TLS服务器凭据私钥时发生致命错误。加密模块返回的错误代码是0x8009030D。内部错误状态为10001。


0
投票

此错误也可以由您自己的计算机触发,而不仅仅是未处理的异常。如果您的服务器/计算机的时钟时间过多,则许多.NET Web服务将拒绝您的请求,并显示未处理的错误。它是从他们的角度处理的,但是从你的观点来看未得到处理。检查以确保接收服务器的时钟时间正确。如果需要修复,则必须重置服务或重新启动频道之前重新启动。

我在服务器上遇到此问题,防火墙阻止了Internet时间更新,服务器由于某种原因关闭了时间。所有第三方.NET Web服务都因为拒绝任何Web服务请求而出现故障。深入了解事件查看器有助于确定问题,但调整时钟解决了问题。尽管我们收到了针对未来Web服务调用的Faulted State错误消息,但错误仍然存​​在。


0
投票

服务器将自动中止在没有收到消息的连接上等待接收超时的持续时间(默认为10分钟)。这是一种DoS缓解措施,可防止客户端强制服务器无限期地打开连接。

由于服务器因为空闲而中止连接,因此客户端会获得此异常。

您可以通过在服务器绑定上配置接收超时来控制服务器允许连接在中止之前空闲多长时间。图片来源:T.R.Vishwanath - MSFT


0
投票

我知道这是一个较旧的帖子,但是当你无法改变安全性时要注意的一件事是确保你的用户名和密码已经设置好。

我有一个使用authenticationMode作为UserNameOverTransport的服务,当没有为服务客户端设置用户名和密码时,我会收到此错误。


0
投票

对我来说这是一个负载均衡器/网址问题。负载均衡器后面的Web服务使用完整URL(例如:loadbalancer.mycompany.com)在同一负载均衡器后面调用另一个服务。我通过使用localhost.mycompany.com来调用第二个服务时将其更改为绕过负载均衡器。

我认为负载均衡器会出现某种循环引用问题。


-1
投票

不是这个问题的解决方案,但如果您在使用Ektron eSync时遇到上述错误,则可能是您的数据库磁盘空间不足。

编辑:事实上,这不仅仅是Ektron eSync问题。这可能发生在查询完整数据库的任何服务上。

编辑:磁盘空间不足或阻止访问您需要的目录将导致此问题。


28
投票

要防止服务器陷入故障状态,您必须确保不会引发未处理的异常。如果WCF看到意外的异常,则不再接受任何呼叫 - 安全第一。 避免这种行为的两种可能性:

  1. 使用FaultException(这对于WCF来说并不意外,因此WCF知道服务器仍然是有效状态) 代替 throw new Exception("Error xy in my function") 永远使用 throw new FaultException("Error xy in my function") 也许你可以尝试..捕获整个块并在异常的所有情况下抛出FaultException try { ... some code here } catch (Exception ex) { throw new FaultException(ex.Message) }
  2. 告诉WCF使用Errorhandler处理所有异常。这可以通过几种方式完成,我选择了一个使用属性的简单方法: 我们所要做的就是在想要的服务实现上使用属性[SvcErrorHandlerBehaviour] using System; using System.Collections.ObjectModel; using System.ServiceModel; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher; namespace MainService.Services { /// <summary> /// Provides FaultExceptions for all Methods Calls of a Service that fails with an Exception /// </summary> public class SvcErrorHandlerBehaviourAttribute : Attribute, IServiceBehavior { public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } //implementation not needed public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { } //implementation not needed public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { foreach (ChannelDispatcherBase chanDispBase in serviceHostBase.ChannelDispatchers) { ChannelDispatcher channelDispatcher = chanDispBase as ChannelDispatcher; if (channelDispatcher == null) continue; channelDispatcher.ErrorHandlers.Add(new SvcErrorHandler()); } } } public class SvcErrorHandler: IErrorHandler { public bool HandleError(Exception error) { //You can log th message if you want. return true; } public void ProvideFault(Exception error, MessageVersion version, ref Message msg) { if (error is FaultException) return; FaultException faultException = new FaultException(error.Message); MessageFault messageFault = faultException.CreateMessageFault(); msg = Message.CreateMessage(version, messageFault, faultException.Action); } } }

这是一个简单的例子,你可以通过不使用裸FaultException深入IErrorhandler,但是FaultException<>提供额外信息的类型请参阅IErrorHandler以获取详细示例。


8
投票

事实上,如果在遵循marc_s的建议后不成功,请记住服务器上web.config中服务器绑定配置(或缺少)中的<security>元素可能会导致此异常。例如,服务器期望Message级安全性,客户端配置为None(或者,如果服务器不是Active Directory域的一部分,但远程客户端主机是)。

提示:在这种情况下,客户端应用程序很可能在RDP会话中的管理帐户下直接在服务器计算机上执行时调用Web服务。


7
投票

附加到the faulted event以找出错误发生的原因和时间。

编辑:如果您发布了有关您正在做的事情的更多信息,也会有所帮助。


2
投票

我有一个通过WCF连接到Windows服务的Web客户端。我的网络应用程序抛出相同的错误

通信对象System.ServiceModel.Channels.ServiceChannel不能用于通信,因为它处于Faulted状态我启用了WCF跟踪,这没有多大帮助。最后重新启动Windows服务解决了它,我仍然不知道原因。故障排除应始终从简单开始。这就是一个例子。如果有人有类似的问题,请尝试重新启动该服务。


2
投票

要诊断此问题,请在Visual Studio调试器下运行该服务。使用菜单:Debug | Exceptions并指示在抛出异常时要中断。

抛出的原始异常将比“..在处于Faulted状态”中有更好的错误消息。

例如,我从ServiceHost.Open()获取此异常,但是当我在抛出它时捕获到原始异常时,错误消息是:

服务'MyServiceName'没有应用程序(非基础结构)端点。这可能是因为没有为您的应用程序找到配置文件,或者因为在配置文件中找不到与服务名称匹配的服务元素,或者因为在service元素中没有定义端点。

修复App.config中的拼写错误解决了这个问题。


1
投票

我有另一个问题,我认为在其他答案中没有提到过。

我必须在相同的tcp地址和端口上为端点提供服务。在app.config中,我忘记添加两个端点,因此服务在正确的端口上运行,但服务接口错误。


1
投票

如果在Visual Studio的Debug中看到此消息,则解决方案包含WCF项目。然后打开此WCF项目设置 - >转到“WCF选项”选项卡 - >关闭“调试时启动WCF服务主机...”选项


1
投票

尝试在http asmx服务中使用net.tcp wcf服务端点时遇到了同样的问题。

正如我所看到的,没有人写出具体的答案为什么会出现这个问题,而只是如何正确处理。

我连续几天都在苦苦挣扎,最后我发现问题来自于我的情况。

最初我认为当你引用一个服务时,配置文件将按照与源代码相同的方式配置安全标记,但事实并非如此,我应该手动处理它。就我而言,我只有

<netTcpBinding>
    <binding name="NetTcpBinding_IAuthenticationLoggerService"
    </binding>
</netTcpBinding>`

后来我看到安全部分丢失了,看起来应该是这样的

<netTcpBinding>
    <binding name="NetTcpBinding_IAuthenticationLoggerService" transferMode="Buffered">
      <security mode="None">
        <transport clientCredentialType="None"/>
      </security>
    </binding>
  </netTcpBinding>

我的第二个问题是我在我的源WCF服务上使用transferMode="Streamed",而在客户端我没有任何具体的内容,这很糟糕,因为默认的transferModeBuffered,它在两个地方的源和客户端配置都很重要以同样的方式。

© www.soinside.com 2019 - 2024. All rights reserved.