Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: WCF служба - управление соединениями.  (Прочитано 7054 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« : 04-06-2011 14:18 » 

Если вкратце, то нужно обеспечить дисциплину "одна сессия в один момент времени".

Не знаю, важно ли, но на всякий случай: работаю с именованными каналами (NetNamedPipeBinding для точки подключения, точка одна).

ServiceHost сам управляет инстанцированием службы. Если служба помечена атрибутом ServiceBehavior, через его параметр InstanceContextMode можно управлять режимами инстанцирования. Режимов этих 3 штуки:
- PerCall - на каждое обращение любого клиента создаётся экземпляр службы;
- PerSession - для каждого клиента создаётся экземпляр службы, однако один экземпляр обслуживает весь прикладной протокол взаимодействия клиента и службы; тут имеется тонкость, связанная с таймаутами - при долгом бездействии клиента соединение разрывается и экземпляр службы уничтожается;
- Single - при открытии хоста на приём создаётся единственный экземпляр службы, который обрабатывает все запросы всех клиентов, и уничтожается только при закрытии хоста.

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

Но мне нужно, чтобы одновременно существовала лишь одна сессия. Т.е. пока клиентов нет - ресурсы свободны. Появился клиент - ему отдали ресурсы. Отключился - освободили ресурсы. Режимы Single и PerCall этого не обеспечивают, поскольку не различают клиентов и не отслеживают события их подключения и отключения. Нужное поведение обеспечивает лишь режим PerSession.

Но в режиме PerSession сессия создаётся автоматически для всякого желающего подключиться. Мне неизвестно правило, которое бы контролировало это дело. Поэтому первый вопрос: если кто такое правило знает - просветите.

В классе службы я определил статическую переменную для хранения экземпляра. В конструкторе экземпляра проверяется состояние этой переменной: если она null, то конструктор присваивает свой экземпляр; если в ней уже есть другой экземпляр, то конструктор генерирует исключительную ситуацию и блокирует создание нового экземпляра службы. (Естественно, в критической секции.)

Всё бы ничего, и это даже устойчиво работает в параллельных потоках. Но это плохо работает в параллельных процессах. То ли это исключение, попадающее внутрь ServiceHost, выводит его из строя, то ли ещё чего. Но после такого исключения все последующие клиенты не могут подключиться, даже если первый клиент уже отключился, служба свободна и готова к приёму.

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

Примечания:

1) Свойство ConcurrencyMode = Single атрибут ServiceBehaviour обеспечивает синхронизацию запросов (один запрос в один момент времени), но не сессий. Не предлагать.

2) Свойство MaxConnections у NetNamedPipeBinding выглядит интересно, но почему-то установка его в 1 эффекта не даёт. Может тоже связано с запросами, а не с сессиями - это я ещё детально не выяснил.

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

Какие у кого ещё идеи возникают?

Добавлено через 1 час, 12 минут и 4 секунды:
Да, был у меня баг. Решение с генерацией исключения в конструкторе работает.

Тем не менее, остаётся вопрос: можно ли решить эту задачу средствами конфигурации WCF?
« Последнее редактирование: 04-06-2011 15:32 от dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines