2016-04-04 3 views
3

Я создал службу WCF, которая использует привязку NetTCP.Служба WCF Не удается поймать сбой клиента

Доступ к моей услуге осуществляется клиентом, который сохраняет его канал обратного вызова и использует его для последующего вызова клиента (это постоянное соединение tcp). Все работает нормально, но если я решаю внезапно убить клиента, я получаю исключение SocketException, которое я не могу уловить («существующее соединение было принудительно закрыто удаленным хостом»).

Что я уже пробовал?

  1. Я добавил примерки уловов положения в каждом методе с использованием канала обратного вызова, и даже в верхнем уровне - WCFHost который начинает свою службу.

  2. Я пытался получать как канал и канал обратного вызова и добавить метод для обработки канала поврежденного события:

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

Короче говоря, я пытаюсь обрабатывать исключения Брошенных клиент - на стороне сервера.

+0

Спасибо, но моя проблема в том, что я не могу поймать исключение и поэтому не могу прервать или закрыть канал. Я получаю исключение, которое я вижу в своей Visual Studio, но он не связан ни с одной строкой в ​​коде, и ни одно из моих предложений try-catch не ловит его. –

+0

Можете ли вы предоставить больше кода? –

ответ

0

После долгих исследований выяснилось, что сервер может определять исключения, выданные clien t с использованием события Faulted, о котором я упоминал ранее в моем вопросе (я должен был быть более терпелив при отладке и ждать, пока исключение «залезет» на все уровни, пока не придет к моему коду).

Обратите внимание, что событие выдает исключение только в том случае, если уже слишком поздно: канал уже имеет значение null (а также OperationContext.Current). Я не смог поймать исходное SocketException, которое было вызвано System.ServiceModel.dll, даже когда я попытался использовать IServiceBehavior и IEndpointBehavior (которые устанавливают IChannelInitializer). Когда мой метод ChannelFaulted() был окончательно вызван, не было обнаружено , из-за которого клиент не удался.

0

Есть два пути для службы WCF для поддержки обработки исключений:

1.Defining в serviceDebug.includeExceptionDetailInFaults атрибут «истина» в хост-файла .config 2. Определение includeExceptionDetailInFaults атрибута «истина» на класс обслуживания.

Пример:

Config Решение Файл:

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

... и т.д.

Бросив Exce ption Установка includeExceptionDetailInFaults в true - ваш первый шаг в поддержке исключений в WCF.

Следующий шаг заключается в том, чтобы ваша служба выбрала исключение FaultException (класс в пространстве имен System.ServiceModel.FaultException). Обратите внимание, что вы не можете рассчитывать просто использовать типичный класс исключения, если хотите передать исключения из узла WCF клиенту WCF. Чтобы исключить исключения из привязок 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); 
} 

Выделяют Типы исключений Fault Класс 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

+0

Спасибо за ответ. Я попытался использовать ServiceBehavior, но я все еще не смог поймать исключение (хотя мне удалось увидеть код ApplyDispatcherBehavior в моем отладчике) –

+0

@G. madn Вы попробовали вторую ссылку, которую я прикрепил? –

+1

Да. Информация, которую вы дали, очень полезна для обработки ошибок после их захвата. Однако моя проблема заключалась в том, что я не смог поймать ошибку в первую очередь. То, что я действительно искал, это способ обнаружить крах клиента, чтобы моя служба не хранила свободные соединения для несуществующих клиентов. –