WCF服务无法捕获客户端的崩溃

时间:2016-04-04 12:57:08

标签: c# wcf tcp duplex-channel

我已经创建了一个使用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;
    
  3. 简而言之,我试图处理客户端抛出的异常 - 在服务器端。

2 个答案:

答案 0 :(得分:0)

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

有关详细信息,您可以查看here以及here

答案 1 :(得分:0)

经过大量调查后发现服务器可以检测客户端使用我在前面提到的Faulted事件引发的异常(我应该在调试时更耐心等待,直到异常“爬上”所有级别,直到我的代码。)

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