【问题标题】:WCF service Cannot catch a client's crashWCF 服务无法捕获客户端的崩溃
【发布时间】:2016-04-04 12:57:07
【问题描述】:

我创建了一个使用 NetTCP 绑定的 WCF 服务。

我的服务被客户端访问,保存它的回调通道并在以后使用它来调用客户端(它是一个持久的 tcp 连接)。一切正常,但如果我决定突然终止客户端 - 我会收到一个无法捕获的 SocketException(“现有连接被远程主机强行关闭”)。

我已经尝试过什么?

  1. 我已经在每个使用回调通道的方法中添加了 try-catch 子句,甚至在上层 - 启动我的服务的 WCFHost。

  2. 我尝试同时获取通道和回调通道,并添加一个处理通道故障事件的方法:

    var channel = OperationContext.Current.Channel; 
    channel.Faulted += ChannelFaulted;
    var callbackChannel = OperationContext.Current.GetCallbackChannel<CallbackInterface>();
    var comObj = callbackChannel as ICommunicationObject;
    comObj.Faulted += ChannelFaulted;
    

简而言之,我正在尝试处理客户端抛出的异常 - 在服务器端。

【问题讨论】:

  • 谢谢,但我的问题是我无法捕捉到异常,因此无法中止或关闭频道。我得到一个异常,我可以在我的 Visual Studio 中看到它 - 但它没有链接到代码中的任何行,我的 try-catch 子句都没有捕获它。
  • 你能提供更多代码吗?

标签: c# wcf tcp duplex-channel


【解决方案1】:

WCF 服务支持异常处理有两种方式:

1.在 hosts .config 文件中将 serviceDebug.includeExceptionDetailInFaults 属性定义为“true” 2. 将服务类的 includeExceptionDetailInFaults 属性定义为“true”。

例子:

配置文件解决方案:

<behaviors>
<serviceBehaviors>
<behavior name=”ServiceBehavior”>
<serviceMetadata httpGetEnabled=”true”/>
<serviceDebug includeExceptionDetailInFaults=”true”/>
</behavior>
</serviceBehaviors>
</behaviors>

属性类解决方案:

[ServiceBehavior(IncludeExceptionDetailInFaults=true)]
public class CustomersService : ICustomersService
{
private CustomerDetail customerDetail = null;

…等

抛出异常 将 includeExceptionDetailInFaults 设置为 true 是在 WCF 中支持异常的第一步。

下一步是让您的服务抛出 FaultException 异常(System.ServiceModel.FaultException 命名空间中的一个类)。 请注意,当您希望从 WCF 主机向 WCF 客户端抛出异常时,不能期望简单地使用典型的 Exception 类。 要在 WCF 绑定上引发异常,您需要使用 FaultException 类。

抛出 FaultException 示例

try
{
//Try to do stuff
}
catch
{
throw new FaultException(“Full ruckus!”);
}

捕获 FaultException 示例

现在 WCF 客户端可以捕获 FaultException...

try
{
//Client calls services off the proxy
}
catch(FaultException fa)
{
MessageBox.Show(fa.Message);
}

区分故障异常的类型 FaultException 类是 WCF 异常的通用类。为了确定发生什么类型的 FaultExceptions,您可以使用 FaultCode 类。 在 WCF 服务上,FaultCode 实现将如下所示:

try
{
   //Connect to a database
}
catch
{
   throw new FaultException(“Full ruckus!”, new FaultCode(“DBConnection”));
}

在 WCF 客户端上,FaultCode 实现将如下所示:

 try
    {
       //Call services via the proxy
    }
    catch(FaultException fa)
    {
       switch(fa.Code.Name)
       {
         case “DBConnection”:
           MessageBox.Show(“Cannot connect to database!”);
           break;
         default:
           MessageBox.Show(“fa.message”);
           break;
        }
    }

有关更多信息,您可以查看herehere

【讨论】:

  • 感谢您的回答。我尝试使用 ServiceBehavior,但仍然无法捕获异常(尽管我确实设法在调试器中看到了 ApplyDispatcherBehavior 的代码)
  • @G.疯了你试过我附上的第二个链接吗?
  • 是的。一旦发现错误,您提供的信息对于处理错误非常有用。但是,我的问题是我一开始就无法捕捉到错误。我真正想要的是一种检测客户端崩溃的方法,这样我的服务就不会为不存在的客户端存储空闲连接。
【解决方案2】:

经过大量调查,事实证明服务器可以使用我在前面的问题中提到的 Faulted 事件检测客户端抛出的异常(我在调试时应该更加耐心,并等到异常“爬升”了所有级别,直到到达我的代码)。

但是请注意,事件仅在为时已晚时才捕获异常:通道已经为空(OperationContext.Current 也是如此)。即使我尝试使用 IServiceBehavior 和 IEndpointBehavior(设置了 IChannelInitializer),我也无法捕获 System.ServiceModel.dll 引发的原始 SocketException。当我的 ChannelFaulted() 方法最终被调用时,无法检测哪个客户端失败了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-17
    • 1970-01-01
    • 1970-01-01
    • 2014-04-04
    • 1970-01-01
    • 2013-02-22
    相关资源
    最近更新 更多