C# - WCF Duplex => Инициировать событие при отключении клиента

Я пытаюсь сообщить своей службе, когда один из клиентов отключен.

Я использую wsDualHttpBinding.

В настоящее время я пытаюсь использовать это событие:

OperationContext.Current.Channel.Closed += new EventHandler((sender, e) => ClientIsDisconnected(sender, e, currentCallbackChannel));

Но это событие никогда не запускается...

Пожалуйста, помогите мне узнать, как это будет сделано!

Редактировать :

Благодаря anderhil я, наконец, заменил wsDualHttpBinding на netTcpBinding (с соответствующей конфигурацией, описанной здесь: http://msdn.microsoft.com/en-us/library/ff647180.aspx#Step1).

С netTcpBinding событие Closed срабатывает без проблем... До сих пор не знаю почему, но это работает.


person Oliboy50    schedule 04.06.2013    source источник
comment
так ты ни разу не получил событие? Как вы это проверяете? Где вы используете свой код? (в какой операции) Зачем вам дуплекс?   -  person Andriy Kizym    schedule 04.06.2013
comment
Нет, я еще не получил его. Я тестирую это, закрывая один из моих клиентских WinForm. Я прикрепляю EventHandler, когда один из моих клиентов подключается к службе, сразу после этого я зарегистрировал текущий CallbackChannel в списке каналов. Мне нужен дуплекс, чтобы каждый клиент знал, когда другой клиент отключен.   -  person Oliboy50    schedule 04.06.2013
comment
Я отредактировал свой вопрос, добавив больше кода.   -  person Oliboy50    schedule 04.06.2013
comment
Добавьте какую-нибудь кнопку в WinForm, и когда кнопка нажата, возьмите клиентский канал и вызовите метод .Close() или .Abort(), а затем попробуйте проверить его, нажав кнопку. Также раскомментируйте событие Faulted — в таких случаях эти два события всегда должны идти вместе.   -  person Andriy Kizym    schedule 04.06.2013
comment
Кроме того, интересно, почему эти события не вызываются, но в целом этот метод обработки событий не охватывает случаи, когда ваша клиентская машина будет выключена, или клиентский маршрутизатор выключится, или что-то в этом роде, потому что клиент должен отправить какое-то сообщение, чтобы сообщить службе, что клиент отключается. Так что в вашем случае я бы сделал таймер, который спрашивает всех клиентов, живы ли они.   -  person Andriy Kizym    schedule 04.06.2013
comment
Если я понял, я не должен .close() подключаться к моей службе сразу после того, как я получил то, что хотел? А когда я выйду из клиентского приложения, соединение само закроется? Кажется, я что-то неправильно понял...   -  person Oliboy50    schedule 04.06.2013
comment
давайте продолжим это обсуждение в чате   -  person Andriy Kizym    schedule 04.06.2013


Ответы (2)


Проблема, с которой вы столкнулись, вероятно, связана с WsDualHttpBinding. Если у вас есть эта привязка, создаются два подключения: от клиента к службе и от службы к клиенту.

Когда приложение развертывается через Интернет, оно может создать некоторые проблемы с поддержкой таких приложений, вы должны быть уверены, что люди не находятся за брандмауэром, NAT и т. д., которые могут помешать вашей службе подключиться обратно к клиенту.

Я до сих пор не знаю, почему это не работает на локальной машине при тестировании, но я постараюсь решить эту проблему и обновить ответ.

Как вы рассказали мне более подробно в нашем чате, исходя из характера вашего приложения, лучше использовать NetTcpBinding. В этом случае легче понять, что происходит, потому что создается одно соединение, и вы будете получать уведомления в случае корректного закрытия или прерывания работы клиента.

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

Кроме того, вы можете найти эту хорошую шпаргалку о том, как выбрать связь между сторонами, использующими WCF:

шпаргалка по привязке wcf

person Andriy Kizym    schedule 04.06.2013

Событие Closed должно происходить при корректном отключении; это то, что происходит? Чтобы обнаружить чистое отключение сокета, прослушивайте Faulted событие:

OperationContext.Current.Channel.Faulted += new EventHandler(FaultedHandler);
person Geoff    schedule 04.06.2013
comment
На самом деле, я пробовал оба... Как я могу быть уверен, что событие запущено? Я поместил Console.WriteLine(blabla) в функцию ClientIsDisconnected. Но я даже не уверен, увижу ли я это в выходных данных службы... - person Oliboy50; 04.06.2013
comment
Для отладки сервиса подключитесь к нему; хорошие инструкции находятся здесь - person Geoff; 04.06.2013
comment
Гм... кажется, что моя служба уже подключена.. Можете ли вы привести пример того, как я должен использовать это событие, может быть, я делаю это неправильно. - person Oliboy50; 04.06.2013
comment
EventHandler должен быть подключен до или после того, как я зарегистрирую OperationContext.Current.GetCallbackChannel<IService1Callback>() в своем списке каналов? - person Oliboy50; 04.06.2013