简体   繁体   English

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

[英]WCF service Cannot catch a client's crash

I've created a WCF service which uses a NetTCP binding. 我已经创建了一个使用NetTCP绑定的WCF服务。

My service is accessed by a client, saves its callback channel and uses it to call the client later on (it's a persistent tcp connection). 我的服务由客户端访问,保存其回调通道并稍后使用它来调用客户端(这是一个持久的tcp连接)。 Everything works fine, but if I decide to suddenly kill the client - I get a SocketException which I can't catch ("An existing connection was forcibly closed by the remote host"). 一切正常,但如果我决定突然杀死客户端 - 我得到一个我无法捕获的SocketException(“现有连接被远程主机强行关闭”)。

What have I already tried? 我已经尝试了什么?

  1. I've added try-catch clauses in every method using the callback channel, and even in the upper level - the WCFHost which starts my service. 我在使用回调通道的每个方法中添加了try-catch子句,甚至在上层 - WCFHost中启动了我的服务。

  2. I've tried getting both the channel and the callback channel and adding a method treating the channel faulted event: 我已尝试同时获取通道和回调通道,并添加一个处理通道故障事件的方法:

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

In short, I'm trying to handle exceptions thrown by the client - on the server side. 简而言之,我正在尝试处理客户端抛出的异常 - 在服务器端。

There are two ways for a WCF service to support exception handling: WCF服务有两种支持异常处理的方法:

1.Defining the serviceDebug.includeExceptionDetailInFaults attribute to “true” in the hosts .config file 2. Defining the includeExceptionDetailInFaults attribute to “true” on the service class. 1.在hosts .config文件中将serviceDebug.includeExceptionDetailInFaults属性定义为“true”2.在服务类上将includeExceptionDetailInFaults属性定义为“true”。

Example: 例:

Config File Solution: 配置文件解决方案:

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

Attributed Class Solution: 归属类解决方案:

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

… etc ......等

Throwing the Exception Setting the includeExceptionDetailInFaults to true is your first step in supporting exceptions in WCF. 抛出异常将includeExceptionDetailInFaults设置为true是支持WCF中的异常的第一步。

The next step is to have your service throw the FaultException exception (a class in the System.ServiceModel.FaultException namespace). 下一步是让您的服务抛出FaultException异常(System.ServiceModel.FaultException命名空间中的一个类)。 Note that you cannot expect to simply use the typical Exception class when you wish to throw exceptions from the WCF host to the WCF client. 请注意,当您希望将异常从WCF主机引发到WCF客户端时,您不能指望使用典型的Exception类。 To throw exceptions over the WCF bindings you will need to use the FaultException class. 要在WCF绑定上抛出异常,您需要使用FaultException类。

Throwing FaultException Example : 抛出FaultException示例

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

Catching FaultException Example : 捕获FaultException示例

Now the WCF client can catch the FaultException… 现在WCF客户端可以捕获FaultException ...

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

Distinguish Types of Fault Exceptions The FaultException class is a generic class for WCF exceptions. 区分错误类型的类型 FaultException类是WCF异常的通用类。 In order to determine what type of FaultExceptions occur, you use the FaultCode class. 为了确定发生了什么类型的FaultExceptions,可以使用FaultCode类。 On the WCF service the FaultCode implementation will look something like this: 在WCF服务上,FaultCode实现将如下所示:

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

On the WCF client, the FaultCode implementation will look something like this: 在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;
        }
    }

for more information you can look here and also here 有关更多信息,您可以 此处查看

After much investigation it turns out that a server can detect exceptions thrown by the client using the Faulted event I mentioned earlier in my question (I should have been more patient when debugging, and wait until the exception "climbed" all levels until getting to my code). 经过大量调查后发现服务器可以使用我在前面提到的问题中检测到的Faulted事件检测客户端引发的异常(我应该在调试时更加耐心,等到异常“爬”到所有级别,直到找到我的码)。

Please note, however, that the event catches the exception only when it is too late: the channel is already null (and so is the OperationContext.Current). 但请注意,事件只有在为时已晚时才捕获异常:通道已为空(OperationContext.Current也是如此)。 I couldn't catch the original SocketException thrown by the System.ServiceModel.dll even when I tried using the IServiceBehavior and the IEndpointBehavior (which set an IChannelInitializer). 即使我尝试使用IServiceBehavior和IEndpointBehavior(设置IChannelInitializer),我也无法捕获System.ServiceModel.dll抛出的原始SocketException。 When my ChannelFaulted() method was finally called, there was no way to detect which client failed. 最后调用我的ChannelFaulted()方法时,无法检测哪个客户端失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM