我已经创建了一个使用NetTCP绑定的WCF服务。
我的服务由客户端访问,保存其回调通道并在以后用它来调用客户端(它是一个持久的tcp连接)。一切正常,但如果我决定突然杀死客户端 - 我得到一个我无法捕获的SocketException("现有连接被远程主机强行关闭")。
我已经尝试了什么?
我已经在使用回调频道的每个方法中添加了try-catch子句,甚至在上层 - 我启动服务的WCFHost。
我尝试过同时获取频道和回调频道,并添加一个处理频道出错事件的方法:
var channel = OperationContext.Current.Channel;
channel.Faulted += ChannelFaulted;
var callbackChannel = OperationContext.Current.GetCallbackChannel<CallbackInterface>();
var comObj = callbackChannel as ICommunicationObject;
comObj.Faulted += ChannelFaulted;
简而言之,我试图处理客户端抛出的异常 - 在服务器端。
答案 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;
}
}
答案 1 :(得分:0)
经过大量调查后发现服务器可以检测客户端使用我在前面提到的Faulted事件引发的异常(我应该在调试时更耐心等待,直到异常“爬上”所有级别,直到我的代码。)
但请注意,事件仅在为时已晚时捕获异常:通道已为空(OperationContext.Current也是如此)。即使我尝试使用IServiceBehavior和IEndpointBehavior(设置IChannelInitializer),我也无法捕获System.ServiceModel.dll抛出的原始SocketException。最后调用我的ChannelFaulted()方法时,无法检测哪个客户端失败。