3

我创建了一个使用 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;
    

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

4

2 回答 2

0

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

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

例子:

配置文件解决方案:

<behaviors>
<serviceBehaviors>
<behavior name=”ServiceBehavior”&gt;
<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!”);
}

捕获 FaultException 示例

现在 WCF 客户端可以捕获 FaultException...</p>

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

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

于 2016-04-04T13:28:55.443 回答
0

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

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

于 2016-04-06T08:36:38.910 回答