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



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

我的服务由客户端访问,保存其回调通道,并在以后使用它来调用客户端(它是一个持久的tcp连接)。一切都很好,但如果我决定突然终止客户端,我会得到一个无法捕获的SocketException("远程主机强制关闭了现有连接")。

我已经试过什么了

  1. 我在每个使用回调通道的方法中都添加了try-catch子句,甚至在更高级别的WCFHost中也添加了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;
    

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

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;

…etc

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

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

引发FaultException示例

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

捕获故障异常示例

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

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

区分故障异常的类型FaultException类是WCF异常的泛型类。为了确定发生何种类型的FaultException,可以使用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;
        }
    }

有关更多信息,您可以在此处以及此处查看

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

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

相关内容

  • 没有找到相关文章

最新更新